diff --git a/lib/puppet/face/catalog.rb b/lib/puppet/face/catalog.rb index 0dcde3591..59356d43f 100644 --- a/lib/puppet/face/catalog.rb +++ b/lib/puppet/face/catalog.rb @@ -1,40 +1,49 @@ require 'puppet/face/indirector' Puppet::Face::Indirector.define(:catalog, '0.0.1') do + summary "Compile, save, view, and convert catalogs." + + @longdocs = "This face primarily interacts with the compiling subsystem. + By default, it compiles a catalog using the default manifest and the + hostname from 'certname', but you can choose to retrieve a catalog from + the server by specifying '--from rest'. You can also choose to print any + catalog in 'dot' format (for easy graph viewing with OmniGraffle or Graphviz) + with '--format dot'." + action(:apply) do when_invoked do |catalog, options| report = Puppet::Transaction::Report.new("apply") report.configuration_version = catalog.version Puppet::Util::Log.newdestination(report) begin benchmark(:notice, "Finished catalog run") do catalog.apply(:report => report) end rescue => detail puts detail.backtrace if Puppet[:trace] Puppet.err "Failed to apply catalog: #{detail}" end report.finalize_report report end end action(:download) do when_invoked do |certname, facts, options| Puppet::Resource::Catalog.indirection.terminus_class = :rest facts_to_upload = {:facts_format => :b64_zlib_yaml, :facts => CGI.escape(facts.render(:b64_zlib_yaml))} catalog = nil retrieval_duration = thinmark do catalog = Puppet::Face[:catalog, '0.0.1'].find(certname, facts_to_upload) end catalog = catalog.to_ral catalog.finalize catalog.retrieval_duration = retrieval_duration catalog.write_class_file catalog end end end diff --git a/lib/puppet/face/certificate.rb b/lib/puppet/face/certificate.rb index 77e80f099..5f410fa4c 100644 --- a/lib/puppet/face/certificate.rb +++ b/lib/puppet/face/certificate.rb @@ -1,46 +1,48 @@ require 'puppet/face/indirector' require 'puppet/ssl/host' Puppet::Face::Indirector.define(:certificate, '0.0.1') do + summary "Manage certificates, including signing and revoking them." + # REVISIT: This should use a pre-invoke hook to run the common code that # needs to happen before we invoke any action; that would be much nicer than # the "please repeat yourself" stuff found in here right now. # # option "--ca-location LOCATION" do # type [:whatever, :location, :symbols] # hook :before do |value| # Puppet::SSL::Host.ca_location = value # end # end # # ...but should I pass the arguments as well? # --daniel 2011-04-05 option "--ca-location LOCATION" action :generate do when_invoked do |name, options| Puppet::SSL::Host.ca_location = options[:ca_location].to_sym host = Puppet::SSL::Host.new(name) host.generate_certificate_request host.certificate_request.class.indirection.save(host.certificate_request) end end action :list do when_invoked do |options| Puppet::SSL::Host.ca_location = options[:ca_location].to_sym Puppet::SSL::Host.indirection.search("*", { :for => :certificate_request, }).map { |h| h.inspect } end end action :sign do when_invoked do |name, options| Puppet::SSL::Host.ca_location = options[:ca_location].to_sym host = Puppet::SSL::Host.new(name) host.desired_state = 'signed' Puppet::SSL::Host.indirection.save(host) end end end diff --git a/lib/puppet/face/certificate_request.rb b/lib/puppet/face/certificate_request.rb index 1feba25ab..4e711b25b 100644 --- a/lib/puppet/face/certificate_request.rb +++ b/lib/puppet/face/certificate_request.rb @@ -1,4 +1,5 @@ require 'puppet/face/indirector' Puppet::Face::Indirector.define(:certificate_request, '0.0.1') do + summary "Manage certificate requests." end diff --git a/lib/puppet/face/certificate_revocation_list.rb b/lib/puppet/face/certificate_revocation_list.rb index 6a75aa578..f111586af 100644 --- a/lib/puppet/face/certificate_revocation_list.rb +++ b/lib/puppet/face/certificate_revocation_list.rb @@ -1,4 +1,5 @@ require 'puppet/face/indirector' Puppet::Face::Indirector.define(:certificate_revocation_list, '0.0.1') do + summary "Manage the list of revoked certificates." end diff --git a/lib/puppet/face/config.rb b/lib/puppet/face/config.rb index 45cb6b156..d1f6d5a9e 100644 --- a/lib/puppet/face/config.rb +++ b/lib/puppet/face/config.rb @@ -1,12 +1,14 @@ require 'puppet/face' Puppet::Face.define(:config, '0.0.1') do + summary "Interact with Puppet configuration options." + action(:print) do when_invoked do |*args| options = args.pop Puppet.settings[:configprint] = args.join(",") Puppet.settings.print_config_options nil end end end diff --git a/lib/puppet/face/configurer.rb b/lib/puppet/face/configurer.rb index 74dfb854e..7aebc8da2 100644 --- a/lib/puppet/face/configurer.rb +++ b/lib/puppet/face/configurer.rb @@ -1,12 +1,14 @@ require 'puppet/face' Puppet::Face.define(:configurer, '0.0.1') do + summary "Provides agent-like behavior, with no plugin downloading or reporting." + action(:synchronize) do when_invoked do |certname, options| facts = Puppet::Face[:facts, '0.0.1'].find(certname) catalog = Puppet::Face[:catalog, '0.0.1'].download(certname, facts) report = Puppet::Face[:catalog, '0.0.1'].apply(catalog) report end end end diff --git a/lib/puppet/face/facts.rb b/lib/puppet/face/facts.rb index 8668b2531..caa3cfd54 100644 --- a/lib/puppet/face/facts.rb +++ b/lib/puppet/face/facts.rb @@ -1,18 +1,20 @@ require 'puppet/face/indirector' require 'puppet/node/facts' Puppet::Face::Indirector.define(:facts, '0.0.1') do + summary "Retrieve, store, and view facts." + set_default_format :yaml # Upload our facts to the server action(:upload) do when_invoked do |options| Puppet::Node::Facts.indirection.terminus_class = :facter facts = Puppet::Node::Facts.indirection.find(Puppet[:certname]) Puppet::Node::Facts.indirection.terminus_class = :rest Puppet::Node::Facts.indirection.save(facts) Puppet.notice "Uploaded facts for '#{Puppet[:certname]}'" nil end end end diff --git a/lib/puppet/face/file.rb b/lib/puppet/face/file.rb index 1aa9462dd..547df3e4f 100644 --- a/lib/puppet/face/file.rb +++ b/lib/puppet/face/file.rb @@ -1,5 +1,7 @@ require 'puppet/face/indirector' Puppet::Face::Indirector.define(:file, '0.0.1') do + summary "Retrieve and store files in a filebucket" + set_indirection_name :file_bucket_file end diff --git a/lib/puppet/face/key.rb b/lib/puppet/face/key.rb index 3a11ddb03..c85345167 100644 --- a/lib/puppet/face/key.rb +++ b/lib/puppet/face/key.rb @@ -1,4 +1,8 @@ require 'puppet/face/indirector' Puppet::Face::Indirector.define(:key, '0.0.1') do + summary "Create, save, and remove certificate keys." + + @longdocs = "Keys are created for you automatically when certificate + requests are generated with 'puppet certificate generate'." end diff --git a/lib/puppet/face/node.rb b/lib/puppet/face/node.rb index fd1a548d6..b7ffaf38e 100644 --- a/lib/puppet/face/node.rb +++ b/lib/puppet/face/node.rb @@ -1,5 +1,10 @@ require 'puppet/face/indirector' Puppet::Face::Indirector.define(:node, '0.0.1') do + summary "View and manage nodes" + + @longdocs = "It defaults to using whatever your node + terminus is set as." + set_default_format :yaml end diff --git a/lib/puppet/face/parser.rb b/lib/puppet/face/parser.rb index d4aaaf043..bea146f81 100644 --- a/lib/puppet/face/parser.rb +++ b/lib/puppet/face/parser.rb @@ -1,20 +1,22 @@ require 'puppet/face' require 'puppet/parser' Puppet::Face.define(:parser, '0.0.1') do - action :validate do - when_invoked do |*args| - args.pop - files = args - if files.empty? - files << Puppet[:manifest] - Puppet.notice "No manifest specified. Validating the default manifest #{Puppet[:manifest]}" - end - files.each do |file| - Puppet[:manifest] = file - Puppet::Node::Environment.new(Puppet[:environment]).known_resource_types.clear - end - nil - end - end + summary "Interact directly with the parser" + + action :validate do + when_invoked do |*args| + args.pop + files = args + if files.empty? + files << Puppet[:manifest] + Puppet.notice "No manifest specified. Validating the default manifest #{Puppet[:manifest]}" + end + files.each do |file| + Puppet[:manifest] = file + Puppet::Node::Environment.new(Puppet[:environment]).known_resource_types.clear + end + nil + end + end end diff --git a/lib/puppet/face/report.rb b/lib/puppet/face/report.rb index 6e6f0b335..4de25ef92 100644 --- a/lib/puppet/face/report.rb +++ b/lib/puppet/face/report.rb @@ -1,15 +1,17 @@ require 'puppet/face/indirector' Puppet::Face::Indirector.define(:report, '0.0.1') do + summary "Create, display, and submit reports" + action(:submit) do when_invoked do |report, options| begin Puppet::Transaction::Report.terminus_class = :rest report.save rescue => detail puts detail.backtrace if Puppet[:trace] Puppet.err "Could not send report: #{detail}" end end end end diff --git a/lib/puppet/face/resource.rb b/lib/puppet/face/resource.rb index d162f728a..908b2e462 100644 --- a/lib/puppet/face/resource.rb +++ b/lib/puppet/face/resource.rb @@ -1,4 +1,5 @@ require 'puppet/face/indirector' Puppet::Face::Indirector.define(:resource, '0.0.1') do + summary "Interact directly with resources via the RAL, like ralsh" end diff --git a/lib/puppet/face/resource_type.rb b/lib/puppet/face/resource_type.rb index 0cdbd719f..fe86eb873 100644 --- a/lib/puppet/face/resource_type.rb +++ b/lib/puppet/face/resource_type.rb @@ -1,4 +1,5 @@ require 'puppet/face/indirector' Puppet::Face::Indirector.define(:resource_type, '0.0.1') do + summary "View resource types, classes, and nodes from all manifests" end diff --git a/lib/puppet/face/status.rb b/lib/puppet/face/status.rb index 7085e7cd7..2a0956ee3 100644 --- a/lib/puppet/face/status.rb +++ b/lib/puppet/face/status.rb @@ -1,4 +1,5 @@ require 'puppet/face/indirector' Puppet::Face::Indirector.define(:status, '0.0.1') do + summary "View status information" end diff --git a/spec/lib/puppet/face/basetest.rb b/spec/lib/puppet/face/basetest.rb index 00616f74f..9a658b685 100755 --- a/spec/lib/puppet/face/basetest.rb +++ b/spec/lib/puppet/face/basetest.rb @@ -1 +1,3 @@ -Puppet::Face.define(:basetest, '0.0.1') +Puppet::Face.define(:basetest, '0.0.1') do + summary "This is just so tests don't fail" +end diff --git a/spec/unit/application/indirection_base_spec.rb b/spec/unit/application/indirection_base_spec.rb index 63ab11eed..dedadb4ad 100755 --- a/spec/unit/application/indirection_base_spec.rb +++ b/spec/unit/application/indirection_base_spec.rb @@ -1,38 +1,39 @@ #!/usr/bin/env rspec require 'spec_helper' require 'puppet/application/indirection_base' require 'puppet/face/indirector' ######################################################################## # Stub for testing; the names are critical, sadly. --daniel 2011-03-30 class Puppet::Application::TestIndirection < Puppet::Application::IndirectionBase end face = Puppet::Face::Indirector.define(:testindirection, '0.0.1') do + summary "fake summary" end # REVISIT: This horror is required because we don't allow anything to be # :current except for if it lives on, and is loaded from, disk. --daniel 2011-03-29 face.instance_variable_set('@version', :current) Puppet::Face.register(face) ######################################################################## describe Puppet::Application::IndirectionBase do subject { Puppet::Application::TestIndirection.new } it "should accept a terminus command line option" do # It would be nice not to have to stub this, but whatever... writing an # entire indirection stack would cause us more grief. --daniel 2011-03-31 terminus = mock("test indirection terminus") Puppet::Indirector::Indirection.expects(:instance). with(:testindirection).twice.returns() subject.command_line. instance_variable_set('@args', %w{--terminus foo save}) # Not a very nice thing. :( $stderr.stubs(:puts) expect { subject.run }.should raise_error SystemExit end end diff --git a/spec/unit/face/help_spec.rb b/spec/unit/face/help_spec.rb index e67f29e07..33e13a240 100755 --- a/spec/unit/face/help_spec.rb +++ b/spec/unit/face/help_spec.rb @@ -1,112 +1,123 @@ require 'spec_helper' require 'puppet/face/help' describe Puppet::Face[:help, '0.0.1'] do it "should have a help action" do subject.should be_action :help end it "should have a default action of help" do pending "REVISIT: we don't support default actions yet" end it "should accept a call with no arguments" do expect { subject.help() }.should_not raise_error end it "should accept a face name" do expect { subject.help(:help) }.should_not raise_error end it "should accept a face and action name" do expect { subject.help(:help, :help) }.should_not raise_error end it "should fail if more than a face and action are given" do expect { subject.help(:help, :help, :for_the_love_of_god) }. should raise_error ArgumentError end it "should treat :current and 'current' identically" do subject.help(:help, :version => :current).should == subject.help(:help, :version => 'current') end it "should complain when the request version of a face is missing" do expect { subject.help(:huzzah, :bar, :version => '17.0.0') }. should raise_error Puppet::Error end it "should find a face by version" do face = Puppet::Face[:huzzah, :current] subject.help(:huzzah, :version => face.version). should == subject.help(:huzzah, :version => :current) end context "when listing subcommands" do subject { Puppet::Face[:help, :current].help } + RSpec::Matchers.define :have_a_summary do + match do |instance| + instance.summary.is_a?(String) + end + end + # Check a precondition for the next block; if this fails you have # something odd in your set of face, and we skip testing things that # matter. --daniel 2011-04-10 it "should have at least one face with a summary" do Puppet::Face.faces.should be_any do |name| Puppet::Face[name, :current].summary end end Puppet::Face.faces.each do |name| face = Puppet::Face[name, :current] summary = face.summary - it { should =~ %r{ #{name} } } - it { should =~ %r{ #{name} +#{summary}} } if summary + it "should list the '#{name}' face in the general help" do + should =~ %r{ #{name} } + end + + it "should have a summary for #{name}" do + face.should have_a_summary + end end Puppet::Face[:help, :current].legacy_applications.each do |appname| it { should =~ %r{ #{appname} } } summary = Puppet::Face[:help, :current].horribly_extract_summary_from(appname) summary and it { should =~ %r{ #{summary}\b} } end end context "#legacy_applications" do subject { Puppet::Face[:help, :current].legacy_applications } # If we don't, these tests are ... less than useful, because they assume # it. When this breaks you should consider ditching the entire feature # and tests, but if not work out how to fake one. --daniel 2011-04-11 it { should have_at_least(1).item } # Meh. This is nasty, but we can't control the other list; the specific # bug that caused these to be listed is annoyingly subtle and has a nasty # fix, so better to have a "fail if you do something daft" trigger in # place here, I think. --daniel 2011-04-11 %w{face_base indirection_base}.each do |name| it { should_not include name } end end context "help for legacy applications" do subject { Puppet::Face[:help, :current] } let :appname do subject.legacy_applications.first end # This test is purposely generic, so that as we eliminate legacy commands # we don't get into a loop where we either test a face-based replacement # and fail to notice breakage, or where we have to constantly rewrite this # test and all. --daniel 2011-04-11 it "should return the legacy help when given the subcommand" do help = subject.help(appname) help.should =~ /puppet-#{appname}/ %w{SYNOPSIS USAGE DESCRIPTION OPTIONS COPYRIGHT}.each do |heading| help.should =~ /^#{heading}$/ end end it "should fail when asked for an action on a legacy command" do expect { subject.help(appname, :whatever) }. to raise_error ArgumentError, /Legacy subcommands don't take actions/ end end end