Last active
December 25, 2015 23:49
-
-
Save trevor-vaughan/7059427 to your computer and use it in GitHub Desktop.
Material for the walkthrough of storing Puppet provider metadata for single instance application hosted at https://www.onyxpoint.com/storing-puppet-provider-metadata-for-single-instance-application.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@@demo_classvars = { | |
# This provider is set up to only target *one* file. To target | |
# multiple files, you'll need to do some creative adjustment to | |
# how your provider works. | |
:target_file => "/tmp/demo_provider.txt", | |
# The original content of the target file (if any). | |
:old_content => "", | |
# The new content of the target file. | |
# Since we're ordered, we'll hash off of the order and title. | |
:new_content => {}, | |
# Don't read the file every time. | |
# This is essentially a prefetch without the magic. | |
:initialized => false, | |
# How many resources do we have of the demo type? | |
:num_demo_resources => 0, | |
# How many times have we hit the demo provider? | |
:num_runs => 0 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
demo { 'name one': | |
order => '5', | |
content => 'This is some line' | |
} | |
demo { 'name two': | |
content => 'Just some random stuff' | |
} | |
demo { 'name three': | |
order => '2', | |
content => 'W00t!' | |
} | |
demo { 'name four': | |
content => 'Some more random stuff' | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 'demo' Puppet Type | |
# | |
# Copyright 2013 Onyx Point, Inc. | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License at | |
# | |
# http://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
# See the License for the specific language governing permissions and | |
# limitations under the License. | |
# | |
module Puppet | |
newtype(:demo) do | |
@doc = <<-EOM | |
A demo type for showing how to use final provider execution. | |
Puts together a file at /tmp/demo_provider.txt with ordered | |
lines based on the combination of the 'order' and 'name' | |
parameters. | |
EOM | |
def initialize(args) | |
super(args) | |
end | |
newparam(:name) do | |
desc "An arbitrary, but unique, name for the resource." | |
isnamevar | |
end | |
newparam(:order) do | |
desc <<-EOM | |
The numeric order in which items should be arranged. | |
In the case of a tie, resources are ordered by :name. | |
Default: 100 | |
EOM | |
newvalues(/^(\d+)$/) | |
defaultto('100') | |
end | |
newproperty(:content) do | |
desc <<-EOM | |
The actual content of the line in the file. | |
EOM | |
isrequired | |
def change_to_s(current_value,new_value) | |
return "Changing\n'#{current_value[:orig]}'\nTo\n'#{current_value[:new]}'" | |
end | |
end | |
validate do | |
if not self[:content] then | |
raise(ArgumentError,"Hey, where's the content?") | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 'demo' Puppet Provider | |
# | |
# Copyright 2013 Onyx Point, Inc. | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License at | |
# | |
# http://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
# See the License for the specific language governing permissions and | |
# limitations under the License. | |
# | |
Puppet::Type.type(:demo).provide(:demo) do | |
# The class variables are global to ALL providers. Make sure you | |
# never reuse names! | |
# An easy way to do this is to use @@<providername>_classvars since | |
# the provider name has to be globally unique. | |
@@demo_classvars = { | |
# This provider is set up to only target *one* file. To target | |
# multiple files, you'll need to do some creative adjustment to | |
# how your provider works. | |
:target_file => "/tmp/demo_provider.txt", | |
# The original content of the target file (if any). | |
:old_content => "", | |
# The new content of the target file. | |
# Since we're ordered, we'll hash off of the order and title. | |
:new_content => {}, | |
# Don't read the file every time. | |
# This is essentially a prefetch without the magic. | |
:initialized => false, | |
# How many resources do we have of the demo type? | |
:num_demo_resources => 0, | |
# How many times have we hit the demo provider? | |
:num_runs => 0 | |
} | |
def initialize(*args) | |
super(*args) | |
# Check to see if we've already initialized. | |
if not @@demo_classvars[:initialized] then | |
# Load the old file content (if any). | |
if File.file?(@@demo_classvars[:target_file]) then | |
Puppet::Util::FileLocking.readlock(@@demo_classvars[:target_file]) { |fh| | |
# In this case, we're ignoring trailing spaces. | |
@@demo_classvars[:old_content] = fh.read.strip | |
} | |
end | |
@@demo_classvars[:initialized] = true | |
end | |
end | |
def content | |
@@demo_classvars[:num_runs] += 1 | |
# Only run through the catalog once. | |
if @@demo_classvars[:num_demo_resources] == 0 then | |
# How many resources (lines) are we managing? | |
@@demo_classvars[:num_demo_resources] = | |
# If you had other requirements for matching, then you could | |
# process on other type attributes in the catalog. | |
resource.catalog.resources.find_all{ |x| | |
x.is_a?(Puppet::Type.type(:demo)) | |
}.count | |
end | |
# Normally, you would do any target manipulation in the | |
# prop=(should) # method. | |
# | |
# However, in this case, this resource may not actually be | |
# handling the manipulation of the target file so you have to do | |
# the in-memory manipulation in the comparator. | |
@@demo_classvars[:new_content]["#{resource[:order]}_#{resource[:name]}"] = | |
resource[:content] | |
# You do not want each resource to drop a log into the log file, | |
# only the last one. So we only declare a change on the last | |
# entry. | |
if @@demo_classvars[:num_runs] == @@demo_classvars[:num_demo_resources] then | |
if collate_output != @@demo_classvars[:old_content] then | |
return { | |
:orig => @@demo_classvars[:old_content], | |
:new => collate_output | |
} | |
end | |
end | |
# We are not ready to do anything yet, just return yourself so that | |
# the resource doesn't trigger. | |
return resource[:content] | |
end | |
def content=(should) | |
# Don't do anything here, just wait for the flush. | |
# We have to wait for all other potential properties to be handled | |
# prior to the final dump. | |
end | |
def flush | |
# If we've gotten here, then there was something to do. However, | |
# we should only get here if all resources have run since nothing | |
# else will actually trigger the event. | |
Puppet::Util::FileLocking.writelock(@@demo_classvars[:target_file],0644) { |fh| | |
fh.rewind | |
fh.puts(collate_output) | |
} | |
end | |
private | |
# Sort by the key and output the resulting text. | |
def collate_output | |
toret = @@demo_classvars[:new_content].keys.sort_by{ |x| | |
human_sort(x) | |
}.map{ |x| | |
@@demo_classvars[:new_content][x] | |
}.join("\n") | |
return toret | |
end | |
def human_sort(obj) | |
# This regex taken from | |
# http://www.bofh.org.uk/2007/12/16/comprehensible-sorting-in-ruby | |
obj.to_s.split(/((?:(?:^|\s)[-+])?(?:\.\d+|\d+(?:\.\d+?(?:[eE]\d+)?(?:$|(?![eE\.])))?))/ms).map { |v| | |
Float(v) rescue v.downcase | |
} | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 'demo' Puppet Type | |
# | |
# Copyright 2013 Onyx Point, Inc. | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License at | |
# | |
# http://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
# See the License for the specific language governing permissions and | |
# limitations under the License. | |
# | |
module Puppet | |
newtype(:demo) do | |
@doc = <<-EOM | |
A demo type for showing how to use final provider execution. | |
Puts together a file at /tmp/demo_provider.txt with ordered | |
lines based on the combination of the 'order' and 'name' | |
parameters. | |
EOM | |
def initialize(args) | |
super(args) | |
end | |
newparam(:name) do | |
desc "An arbitrary, but unique, name for the resource." | |
isnamevar | |
end | |
newparam(:order) do | |
desc <<-EOM | |
The numeric order in which items should be arranged. | |
In the case of a tie, resources are ordered by :name. | |
Default: 100 | |
EOM | |
newvalues(/^(\d+)$/) | |
defaultto('100') | |
end | |
newproperty(:content) do | |
desc <<-EOM | |
The actual content of the line in the file. | |
EOM | |
isrequired | |
def change_to_s(current_value,new_value) | |
return "Changing\n'#{current_value[:orig]}'\nTo\n'#{current_value[:new]}'" | |
end | |
end | |
validate do | |
if not self[:content] then | |
raise(ArgumentError,"Hey, where's the content?") | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
demo { 'section one': | |
order => '5', | |
content => 'This is section one' | |
} | |
demo { 'section two': | |
order => '1', | |
content => 'This is section two but will be before section one' | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mkdir -p /etc/puppet/modules/demo/lib/puppet/type | |
mkdir -p /etc/puppet/modules/demo/lib/puppet/provider/demo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Puppet::Type.type(:demo).provide(:demo) do |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def content | |
@@demo_classvars[:num_runs] += 1 | |
# Only run through the catalog once. | |
if @@demo_classvars[:num_demo_resources] == 0 then | |
# How many resources (lines) are we managing? | |
@@demo_classvars[:num_demo_resources] = | |
# If you had other requirements for matching, then you could | |
# process on other type attributes in the catalog. | |
resource.catalog.resources.find_all{ |x| | |
x.is_a?(Puppet::Type.type(:demo)) | |
}.count | |
end | |
# Normally, you would do any target manipulation in the | |
# prop=(should) # method. | |
# | |
# However, in this case, this resource may not actually be | |
# handling the manipulation of the target file so you have to do | |
# the in-memory manipulation in the comparator. | |
@@demo_classvars[:new_content]["#{resource[:order]}_#{resource[:name]}"] = | |
resource[:content] | |
# You do not want each resource to drop a log into the log file, | |
# only the last one. So we only declare a change on the last | |
# entry. | |
if @@demo_classvars[:num_runs] == @@demo_classvars[:num_demo_resources] then | |
if collate_output != @@demo_classvars[:old_content] then | |
return { | |
:orig => @@demo_classvars[:old_content], | |
:new => collate_output | |
} | |
end | |
end | |
# We are not ready to do anything yet, just return yourself so that | |
# the resource doesn't trigger. | |
return resource[:content] | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def content=(should) | |
# Don't do anything here, just wait for the flush. | |
# We have to wait for all other potential properties to be handled | |
# prior to the final dump. | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def flush | |
# If we've gotten here, then there was something to do. However, | |
# we should only get here if all resources have run since nothing | |
# else will actually trigger the event. | |
Puppet::Util::FileLocking.writelock(@@demo_classvars[:target_file],0644) { |fh| | |
fh.rewind | |
fh.puts(collate_output) | |
} | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private | |
# Sort by the key and output the resulting text. | |
def collate_output | |
toret = @@demo_classvars[:new_content].keys.sort_by{ |x| | |
human_sort(x) | |
}.map{ |x| | |
@@demo_classvars[:new_content][x] | |
}.join("\n") | |
return toret | |
end | |
def human_sort(obj) | |
# This regex taken from | |
# http://www.bofh.org.uk/2007/12/16/comprehensible-sorting-in-ruby | |
obj.to_s.split(/((?:(?:^|\s)[-+])?(?:\.\d+|\d+(?:\.\d+?(?:[eE]\d+)?(?:$|(?![eE\.])))?))/ms).map { |v| | |
Float(v) rescue v.downcase | |
} | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def initialize(*args) | |
super(*args) | |
# Check to see if we've already initialized. | |
if not @@demo_classvars[:initialized] then | |
# Load the old file content (if any). | |
if File.file?(@@demo_classvars[:target_file]) then | |
Puppet::Util::FileLocking.readlock(@@demo_classvars[:target_file]) { |fh| | |
# In this case, we're ignoring trailing spaces. | |
@@demo_classvars[:old_content] = fh.read.strip | |
} | |
end | |
@@demo_classvars[:initialized] = true | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment