summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/puppet/application/puppet.rb50
-rw-r--r--lib/puppet/configurer.rb4
-rwxr-xr-xspec/integration/application/puppet.rb30
-rw-r--r--spec/unit/application/puppet.rb130
-rwxr-xr-xspec/unit/configurer.rb8
5 files changed, 187 insertions, 35 deletions
diff --git a/lib/puppet/application/puppet.rb b/lib/puppet/application/puppet.rb
index ee848a503..dd752846c 100644
--- a/lib/puppet/application/puppet.rb
+++ b/lib/puppet/application/puppet.rb
@@ -16,6 +16,10 @@ Puppet::Application.new(:puppet) do
option("--use-nodes")
option("--detailed-exitcodes")
+ option("--apply catalog", "-a catalog") do |arg|
+ options[:catalog] = arg
+ end
+
option("--logdest LOGDEST", "-l") do |arg|
begin
Puppet::Util::Log.newdestination(arg)
@@ -26,7 +30,37 @@ Puppet::Application.new(:puppet) do
end
dispatch do
- return Puppet[:parseonly] ? :parseonly : :main
+ if options[:catalog]
+ :apply
+ elsif Puppet[:parseonly]
+ :parseonly
+ else
+ :main
+ end
+ end
+
+ command(:apply) do
+ require 'puppet/configurer'
+
+ if options[:catalog] == "-"
+ text = $stdin.read
+ else
+ text = File.read(options[:catalog])
+ end
+
+ begin
+ catalog = JSON.parse(text)
+ unless catalog.is_a?(Puppet::Resource::Catalog)
+ catalog = Puppet::Resource::Catalog.json_create(catalog)
+ end
+ rescue => detail
+ raise Puppet::Error, "Could not deserialize catalog from json: %s" % detail
+ end
+
+ catalog = catalog.to_ral
+
+ configurer = Puppet::Configurer.new
+ configurer.run :catalog => catalog
end
command(:parseonly) do
@@ -40,6 +74,13 @@ Puppet::Application.new(:puppet) do
end
command(:main) do
+ # Set our code or file to use.
+ if options[:code] or ARGV.length == 0
+ Puppet[:code] = options[:code] || STDIN.read
+ else
+ Puppet[:manifest] = ARGV.shift
+ end
+
# Collect our facts.
facts = Puppet::Node::Facts.find(Puppet[:certname])
@@ -126,12 +167,5 @@ Puppet::Application.new(:puppet) do
elsif options[:verbose]
Puppet::Util::Log.level = :info
end
-
- # Set our code or file to use.
- if options[:code] or ARGV.length == 0
- Puppet[:code] = options[:code] || STDIN.read
- else
- Puppet[:manifest] = ARGV.shift
- end
end
end
diff --git a/lib/puppet/configurer.rb b/lib/puppet/configurer.rb
index 8ec0b0055..81845f5cf 100644
--- a/lib/puppet/configurer.rb
+++ b/lib/puppet/configurer.rb
@@ -130,7 +130,9 @@ class Puppet::Configurer
def run(options = {})
prepare()
- unless catalog = retrieve_catalog
+ if catalog = options[:catalog]
+ options.delete(:catalog)
+ elsif ! catalog = retrieve_catalog
Puppet.err "Could not retrieve catalog; skipping run"
return
end
diff --git a/spec/integration/application/puppet.rb b/spec/integration/application/puppet.rb
new file mode 100755
index 000000000..0047dd5a3
--- /dev/null
+++ b/spec/integration/application/puppet.rb
@@ -0,0 +1,30 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet_spec/files'
+
+require 'puppet/application/puppet'
+
+describe "Puppet" do
+ include PuppetSpec::Files
+
+ it "should be able to apply catalogs provided in a file in json" do
+ file_to_create = tmpfile("json_catalog")
+ catalog = Puppet::Resource::Catalog.new
+ resource = Puppet::Resource.new(:file, file_to_create, :content => "my stuff")
+ catalog.add_resource resource
+
+ manifest = tmpfile("manifest")
+
+ File.open(manifest, "w") { |f| f.print catalog.to_json }
+
+ puppet = Puppet::Application[:puppet]
+ puppet.options[:catalog] = manifest
+
+ puppet.apply
+
+ File.should be_exist(file_to_create)
+ File.read(file_to_create).should == "my stuff"
+ end
+end
diff --git a/spec/unit/application/puppet.rb b/spec/unit/application/puppet.rb
index 9256b00dc..ca1203405 100644
--- a/spec/unit/application/puppet.rb
+++ b/spec/unit/application/puppet.rb
@@ -112,42 +112,25 @@ describe "Puppet" do
lambda { @puppet.run_setup }.should raise_error(SystemExit)
end
- it "should set the code to run from --code" do
- @puppet.options.stubs(:[]).with(:code).returns("code to run")
- Puppet.expects(:[]=).with(:code,"code to run")
-
- @puppet.run_setup
- end
-
- it "should set the code to run from STDIN if no arguments" do
- ARGV.stubs(:length).returns(0)
- STDIN.stubs(:read).returns("code to run")
-
- Puppet.expects(:[]=).with(:code,"code to run")
-
- @puppet.run_setup
- end
-
- it "should set the manifest if some files are passed on command line" do
- ARGV.stubs(:length).returns(1)
- ARGV.stubs(:shift).returns("site.pp")
-
- Puppet.expects(:[]=).with(:manifest,"site.pp")
-
- @puppet.run_setup
- end
-
end
describe "when executing" do
it "should dispatch to parseonly if parseonly is set" do
+ @puppet.stubs(:options).returns({})
Puppet.stubs(:[]).with(:parseonly).returns(true)
@puppet.get_command.should == :parseonly
end
+ it "should dispatch to 'apply' if it was called with 'apply'" do
+ @puppet.options[:catalog] = "foo"
+
+ @puppet.get_command.should == :apply
+ end
+
it "should dispatch to main if parseonly is not set" do
+ @puppet.stubs(:options).returns({})
Puppet.stubs(:[]).with(:parseonly).returns(false)
@puppet.get_command.should == :main
@@ -203,12 +186,39 @@ describe "Puppet" do
@catalog.stubs(:to_ral).returns(@catalog)
Puppet::Resource::Catalog.stubs(:find).returns(@catalog)
+ STDIN.stubs(:read)
+
@transaction = stub_everything 'transaction'
@catalog.stubs(:apply).returns(@transaction)
@puppet.stubs(:exit)
end
+ it "should set the code to run from --code" do
+ @puppet.options.stubs(:[]).with(:code).returns("code to run")
+ Puppet.expects(:[]=).with(:code,"code to run")
+
+ @puppet.main
+ end
+
+ it "should set the code to run from STDIN if no arguments" do
+ ARGV.stubs(:length).returns(0)
+ STDIN.stubs(:read).returns("code to run")
+
+ Puppet.expects(:[]=).with(:code,"code to run")
+
+ @puppet.main
+ end
+
+ it "should set the manifest if some files are passed on command line" do
+ ARGV.stubs(:length).returns(1)
+ ARGV.stubs(:shift).returns("site.pp")
+
+ Puppet.expects(:[]=).with(:manifest,"site.pp")
+
+ @puppet.main
+ end
+
it "should collect the node facts" do
Puppet::Node::Facts.expects(:find).returns(@facts)
@@ -319,6 +329,74 @@ describe "Puppet" do
end
end
- end
+ describe "the 'apply' command" do
+ before do
+ #Puppet::Resource::Catalog.stubs(:json_create).returns Puppet::Resource::Catalog.new
+ JSON.stubs(:parse).returns Puppet::Resource::Catalog.new
+ end
+
+ it "should read the catalog in from disk if a file name is provided" do
+ @puppet.options[:catalog] = "/my/catalog.json"
+
+ File.expects(:read).with("/my/catalog.json").returns "something"
+
+ @puppet.apply
+ end
+
+ it "should read the catalog in from stdin if '-' is provided" do
+ @puppet.options[:catalog] = "-"
+
+ $stdin.expects(:read).returns "something"
+
+ @puppet.apply
+ end
+
+ it "should deserialize the catalog from json" do
+ @puppet.options[:catalog] = "/my/catalog.json"
+
+ File.expects(:read).returns "something"
+ JSON.expects(:parse).with("something").returns Puppet::Resource::Catalog.new
+
+ @puppet.apply
+ end
+
+ it "should fail helpfully if deserializing fails" do
+ @puppet.options[:catalog] = "/my/catalog.json"
+
+ File.expects(:read).returns "something"
+ JSON.expects(:parse).raises ArgumentError
+
+ lambda { @puppet.apply }.should raise_error(Puppet::Error)
+ end
+
+ it "should convert plain data structures into a catalog if deserialization does not do so" do
+ @puppet.options[:catalog] = "/my/catalog.json"
+
+ File.expects(:read).returns "something"
+ JSON.expects(:parse).with("something").returns({:foo => "bar"})
+ Puppet::Resource::Catalog.expects(:json_create).with({:foo => "bar"}).returns(Puppet::Resource::Catalog.new)
+
+ @puppet.apply
+ end
+
+ it "should convert the catalog to a RAL catalog and use a Configurer instance to apply it" do
+ @puppet.options[:catalog] = "/my/catalog.json"
+
+ File.expects(:read).returns "something"
+
+ catalog = Puppet::Resource::Catalog.new
+ JSON.expects(:parse).returns catalog
+
+ catalog.expects(:to_ral).returns "mycatalog"
+
+ configurer = stub 'configurer'
+ Puppet::Configurer.expects(:new).returns configurer
+
+ configurer.expects(:run).with(:catalog => "mycatalog")
+
+ @puppet.apply
+ end
+ end
+ end
end
diff --git a/spec/unit/configurer.rb b/spec/unit/configurer.rb
index 9cf22c80c..85bdb9dac 100755
--- a/spec/unit/configurer.rb
+++ b/spec/unit/configurer.rb
@@ -57,6 +57,14 @@ describe Puppet::Configurer, "when executing a catalog run" do
@agent.run :one => true
end
+ it "should accept a catalog and use it instead of retrieving a different one" do
+ catalog = stub 'catalog', :retrieval_duration= => nil
+ @agent.expects(:retrieve_catalog).never
+
+ catalog.expects(:apply).with(:one => true)
+ @agent.run :one => true, :catalog => catalog
+ end
+
it "should benchmark how long it takes to apply the catalog" do
@agent.expects(:benchmark).with(:notice, "Finished catalog run")