summaryrefslogtreecommitdiffstats
path: root/lib/puppet/indirector
diff options
context:
space:
mode:
authorNick Lewis <nick@puppetlabs.com>2011-06-08 18:41:16 -0700
committerNick Lewis <nick@puppetlabs.com>2011-06-08 18:41:16 -0700
commit8ccd00963d91f168438eaec4b29a18cd4a1ac583 (patch)
tree85e15c5ef9390454438fb300c5baa38a7f2f5f3e /lib/puppet/indirector
parent376e0f04af01810d00eede4de52744bb8c8e1681 (diff)
parentd4c499dfdbd94f5272278e1ba87a75915607c3d7 (diff)
downloadpuppet-8ccd00963d91f168438eaec4b29a18cd4a1ac583.tar.gz
puppet-8ccd00963d91f168438eaec4b29a18cd4a1ac583.tar.xz
puppet-8ccd00963d91f168438eaec4b29a18cd4a1ac583.zip
Merge branch '2.7rc' into 2.7.x
Diffstat (limited to 'lib/puppet/indirector')
-rw-r--r--lib/puppet/indirector/catalog/static_compiler.rb137
-rw-r--r--lib/puppet/indirector/face.rb14
2 files changed, 145 insertions, 6 deletions
diff --git a/lib/puppet/indirector/catalog/static_compiler.rb b/lib/puppet/indirector/catalog/static_compiler.rb
new file mode 100644
index 000000000..1d92121ed
--- /dev/null
+++ b/lib/puppet/indirector/catalog/static_compiler.rb
@@ -0,0 +1,137 @@
+require 'puppet/node'
+require 'puppet/resource/catalog'
+require 'puppet/indirector/code'
+
+class Puppet::Resource::Catalog::StaticCompiler < Puppet::Indirector::Code
+ def compiler
+ @compiler ||= indirection.terminus(:compiler)
+ end
+
+ def find(request)
+ return nil unless catalog = compiler.find(request)
+
+ raise "Did not get catalog back" unless catalog.is_a?(model)
+
+ catalog.resources.find_all { |res| res.type == "File" }.each do |resource|
+ next unless source = resource[:source]
+ next unless source =~ /^puppet:/
+
+ file = resource.to_ral
+ if file.recurse?
+ add_children(request.key, catalog, resource, file)
+ else
+ find_and_replace_metadata(request.key, resource, file)
+ end
+ end
+
+ catalog
+ end
+
+ def find_and_replace_metadata(host, resource, file)
+ # We remove URL info from it, so it forces a local copy
+ # rather than routing through the network.
+ # Weird, but true.
+ newsource = file[:source][0].sub("puppet:///", "")
+ file[:source][0] = newsource
+
+ raise "Could not get metadata for #{resource[:source]}" unless metadata = file.parameter(:source).metadata
+
+ replace_metadata(host, resource, metadata)
+ end
+
+ def replace_metadata(host, resource, metadata)
+ [:mode, :owner, :group].each do |param|
+ resource[param] ||= metadata.send(param)
+ end
+
+ resource[:ensure] = metadata.ftype
+ if metadata.ftype == "file"
+ unless resource[:content]
+ resource[:content] = metadata.checksum
+ resource[:checksum] = metadata.checksum_type
+ end
+ end
+
+ store_content(resource) if resource[:ensure] == "file"
+ old_source = resource.delete(:source)
+ Puppet.info "Metadata for #{resource} in catalog for '#{host}' added from '#{old_source}'"
+ end
+
+ def add_children(host, catalog, resource, file)
+ file = resource.to_ral
+
+ children = get_child_resources(host, catalog, resource, file)
+
+ remove_existing_resources(children, catalog)
+
+ children.each do |name, res|
+ catalog.add_resource res
+ catalog.add_edge(resource, res)
+ end
+ end
+
+ def get_child_resources(host, catalog, resource, file)
+ sourceselect = file[:sourceselect]
+ children = {}
+
+ source = resource[:source]
+
+ # This is largely a copy of recurse_remote in File
+ total = file[:source].collect do |source|
+ next unless result = file.perform_recursion(source)
+ return if top = result.find { |r| r.relative_path == "." } and top.ftype != "directory"
+ result.each { |data| data.source = "#{source}/#{data.relative_path}" }
+ break result if result and ! result.empty? and sourceselect == :first
+ result
+ end.flatten
+
+ # This only happens if we have sourceselect == :all
+ unless sourceselect == :first
+ found = []
+ total.reject! do |data|
+ result = found.include?(data.relative_path)
+ found << data.relative_path unless found.include?(data.relative_path)
+ result
+ end
+ end
+
+ total.each do |meta|
+ # This is the top-level parent directory
+ if meta.relative_path == "."
+ replace_metadata(host, resource, meta)
+ next
+ end
+ children[meta.relative_path] ||= Puppet::Resource.new(:file, File.join(file[:path], meta.relative_path))
+
+ # I think this is safe since it's a URL, not an actual file
+ children[meta.relative_path][:source] = source + "/" + meta.relative_path
+ replace_metadata(host, children[meta.relative_path], meta)
+ end
+
+ children
+ end
+
+ def remove_existing_resources(children, catalog)
+ existing_names = catalog.resources.collect { |r| r.to_s }
+
+ both = (existing_names & children.keys).inject({}) { |hash, name| hash[name] = true; hash }
+
+ both.each { |name| children.delete(name) }
+ end
+
+ def store_content(resource)
+ @summer ||= Object.new
+ @summer.extend(Puppet::Util::Checksums)
+
+ type = @summer.sumtype(resource[:content])
+ sum = @summer.sumdata(resource[:content])
+
+ if Puppet::FileBucket::File.indirection.find("#{type}/#{sum}")
+ Puppet.info "Content for '#{resource[:source]}' already exists"
+ else
+ Puppet.info "Storing content for source '#{resource[:source]}'"
+ content = Puppet::FileServing::Content.find(resource[:source])
+ Puppet::FileBucket::File.new(content.content).save
+ end
+ end
+end
diff --git a/lib/puppet/indirector/face.rb b/lib/puppet/indirector/face.rb
index 756306a2f..ead3f4b46 100644
--- a/lib/puppet/indirector/face.rb
+++ b/lib/puppet/indirector/face.rb
@@ -2,7 +2,7 @@ require 'puppet/face'
class Puppet::Indirector::Face < Puppet::Face
option "--terminus TERMINUS" do
- summary "The indirector terminus to use for this action."
+ summary "The indirector terminus to use."
description <<-EOT
Indirector faces expose indirected subsystems of Puppet. These
subsystems are each able to retrieve and alter a specific type of data
@@ -61,11 +61,12 @@ class Puppet::Indirector::Face < Puppet::Face
end
action :save do
- summary "Create or overwrite an object."
+ summary "API only: create or overwrite an object."
arguments "<object>"
description <<-EOT
- Create or overwrite an object. Save actions cannot currently be
- invoked from the command line, and are for API use only.
+ API only: create or overwrite an object. As the Faces framework does not
+ currently accept data from STDIN, save actions cannot currently be invoked
+ from the command line.
EOT
when_invoked { |key, options| call_indirection_method(:save, key, options) }
end
@@ -80,8 +81,9 @@ class Puppet::Indirector::Face < Puppet::Face
action :info do
summary "Print the default terminus class for this face."
description <<-EOT
- Prints the default terminus class for this face. Note that
- different run modes may have different default terminuses.
+ Prints the default terminus class for this subcommand. Note that different
+ run modes may have different default termini; when in doubt, specify the
+ run mode with the '--mode' option.
EOT
when_invoked do |*args|