summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/ralsh187
-rw-r--r--lib/puppet/application/ralsh.rb166
-rw-r--r--spec/unit/application/ralsh.rb230
3 files changed, 398 insertions, 185 deletions
diff --git a/bin/ralsh b/bin/ralsh
index 5ff43c39b..2c9ac5d64 100755
--- a/bin/ralsh
+++ b/bin/ralsh
@@ -85,188 +85,5 @@
# Copyright (c) 2005-2007 Reductive Labs, LLC
# Licensed under the GNU Public License
-
-require 'getoptlong'
-require 'puppet'
-
-options = [
- [ "--debug", "-d", GetoptLong::NO_ARGUMENT ],
- [ "--verbose", "-v", GetoptLong::NO_ARGUMENT ],
- [ "--types", "-t", GetoptLong::NO_ARGUMENT ],
- [ "--param", "-p", GetoptLong::REQUIRED_ARGUMENT ],
- [ "--host", "-H", GetoptLong::REQUIRED_ARGUMENT ],
- [ "--edit", "-e", GetoptLong::NO_ARGUMENT ],
- [ "--help", "-h", GetoptLong::NO_ARGUMENT ]
-]
-
-# Add all of the config parameters as valid options.
-Puppet.settings.addargs(options)
-
-result = GetoptLong.new(*options)
-
-debug = false
-verbose = false
-edit = false
-extra_params = []
-host = nil
-
-result.each { |opt,arg|
- case opt
- when "--host"
- host = arg
- when "--types"
- types = []
- Puppet::Type.loadall
- Puppet::Type.eachtype do |t|
- next if t.name == :component
- types << t.name.to_s
- end
- puts types.sort
- exit
- when "--param"
- extra_params << arg.to_sym
- when "--edit"
- edit = true
- when "--help"
- if Puppet.features.usage?
- RDoc::usage
- else
- puts "install RDoc:usage for help"
- end
- exit
- when "--verbose"
- verbose = true
- when "--debug"
- debug = true
- else
- # Anything else is handled by the config stuff
- Puppet.settings.handlearg(opt, arg)
- end
-}
-
-Puppet::Util::Log.newdestination(:console)
-
-# Now parse the config
-Puppet.parse_config
-
-if debug
- Puppet::Util::Log.level = :debug
-elsif verbose
- Puppet::Util::Log.level = :info
-end
-
-
-if ARGV.length > 0
- type = ARGV.shift
-else
- raise "You must specify the type to display"
-end
-
-name = nil
-params = {}
-if ARGV.length > 0
- name = ARGV.shift
-end
-
-if ARGV.length > 0
- ARGV.each do |setting|
- if setting =~ /^(\w+)=(.+)$/
- params[$1] = $2
- else
- raise "Invalid parameter setting %s" % setting
- end
- end
-end
-
-if edit and host
- raise "You cannot edit a remote host"
-end
-
-typeobj = nil
-
-unless typeobj = Puppet::Type.type(type)
- raise "Could not find type %s" % type
-end
-
-properties = typeobj.properties.collect { |s| s.name }
-
-format = proc {|trans|
- trans.dup.collect do |param, value|
- if value.nil? or value.to_s.empty?
- trans.delete(param)
- elsif value.to_s == "absent" and param.to_s != "ensure"
- trans.delete(param)
- end
-
- unless properties.include?(param) or extra_params.include?(param)
- trans.delete(param)
- end
- end
- trans.to_manifest
-}
-
-text = if host
- client = Puppet::Network::Client.resource.new(:Server => host, :Port => Puppet[:puppetport])
- unless client.read_cert
- raise "client.read_cert failed"
- end
- begin
- # They asked for a single resource.
- if name
- transbucket = [client.describe(type, name)]
- else
- # Else, list the whole thing out.
- transbucket = client.instances(type)
- end
- rescue Puppet::Network::XMLRPCClientError => exc
- raise "client.list(#{type}) failed: #{exc.message}"
- end
- transbucket.sort { |a,b| a.name <=> b.name }.collect(&format)
-else
- if name
- obj = typeobj.create(:name => name, :check => properties)
- vals = obj.retrieve
-
- unless params.empty?
- params.each do |param, value|
- obj[param] = value
- end
- catalog = Puppet::Resource::Catalog.new
- catalog.add_resource obj
- begin
- catalog.apply
- rescue => detail
- if Puppet[:trace]
- puts detail.backtrace
- end
- end
-
- end
- [format.call(obj.to_trans(true))]
- else
- typeobj.instances.collect do |obj|
- next if ARGV.length > 0 and ! ARGV.include? obj.name
- trans = obj.to_trans(true)
- format.call(trans)
- end
- end
-end.compact.join("\n")
-
-if edit
- file = "/tmp/x2puppet-#{Process.pid}.pp"
- begin
- File.open(file, "w") do |f|
- f.puts text
- end
- ENV["EDITOR"] ||= "vi"
- system(ENV["EDITOR"], file)
- system("puppet -v " + file)
- ensure
- #if FileTest.exists? file
- # File.unlink(file)
- #end
- end
-else
- puts text
-end
-
+require 'puppet/application/ralsh'
+Puppet::Application[:ralsh].run
diff --git a/lib/puppet/application/ralsh.rb b/lib/puppet/application/ralsh.rb
new file mode 100644
index 000000000..d15d3e617
--- /dev/null
+++ b/lib/puppet/application/ralsh.rb
@@ -0,0 +1,166 @@
+require 'puppet'
+require 'puppet/application'
+
+Puppet::Application.new(:ralsh) do
+
+ should_not_parse_config
+
+ attr_accessor :host, :extra_params
+
+ preinit do
+ @extra_params = []
+ @host = nil
+ end
+
+ option("--debug","-d")
+ option("--verbose","-v")
+ option("--edit","-e")
+
+ option("--host HOST","-H") do |arg|
+ @host = arg
+ end
+
+ option("--types", "-t") do |arg|
+ types = []
+ Puppet::Type.loadall
+ Puppet::Type.eachtype do |t|
+ next if t.name == :component
+ types << t.name.to_s
+ end
+ puts types.sort
+ exit
+ end
+
+ option("--param PARAM", "-p") do |arg|
+ @extra_params << arg.to_sym
+ end
+
+ command(:main) do
+ if ARGV.length > 0
+ type = ARGV.shift
+ else
+ raise "You must specify the type to display"
+ end
+
+ name = nil
+ params = {}
+ if ARGV.length > 0
+ name = ARGV.shift
+ end
+
+ if ARGV.length > 0
+ ARGV.each do |setting|
+ if setting =~ /^(\w+)=(.+)$/
+ params[$1] = $2
+ else
+ raise "Invalid parameter setting %s" % setting
+ end
+ end
+ end
+
+ if options[:edit] and @host
+ raise "You cannot edit a remote host"
+ end
+
+ typeobj = nil
+
+ unless typeobj = Puppet::Type.type(type)
+ raise "Could not find type %s" % type
+ end
+
+ properties = typeobj.properties.collect { |s| s.name }
+
+ format = proc {|trans|
+ trans.dup.collect do |param, value|
+ if value.nil? or value.to_s.empty?
+ trans.delete(param)
+ elsif value.to_s == "absent" and param.to_s != "ensure"
+ trans.delete(param)
+ end
+
+ unless properties.include?(param) or @extra_params.include?(param)
+ trans.delete(param)
+ end
+ end
+ trans.to_manifest
+ }
+
+ text = if @host
+ client = Puppet::Network::Client.resource.new(:Server => @host, :Port => Puppet[:puppetport])
+ unless client.read_cert
+ raise "client.read_cert failed"
+ end
+ begin
+ # They asked for a single resource.
+ if name
+ transbucket = [client.describe(type, name)]
+ else
+ # Else, list the whole thing out.
+ transbucket = client.instances(type)
+ end
+ rescue Puppet::Network::XMLRPCClientError => exc
+ raise "client.list(#{type}) failed: #{exc.message}"
+ end
+ transbucket.sort { |a,b| a.name <=> b.name }.collect(&format)
+ else
+ if name
+ obj = typeobj.create(:name => name, :check => properties)
+ vals = obj.retrieve
+
+ unless params.empty?
+ params.each do |param, value|
+ obj[param] = value
+ end
+ catalog = Puppet::Resource::Catalog.new
+ catalog.add_resource obj
+ begin
+ catalog.apply
+ rescue => detail
+ if Puppet[:trace]
+ puts detail.backtrace
+ end
+ end
+
+ end
+ [format.call(obj.to_trans(true))]
+ else
+ typeobj.instances.collect do |obj|
+ next if ARGV.length > 0 and ! ARGV.include? obj.name
+ trans = obj.to_trans(true)
+ format.call(trans)
+ end
+ end
+ end.compact.join("\n")
+
+ if options[:edit]
+ file = "/tmp/x2puppet-#{Process.pid}.pp"
+ begin
+ File.open(file, "w") do |f|
+ f.puts text
+ end
+ ENV["EDITOR"] ||= "vi"
+ system(ENV["EDITOR"], file)
+ system("puppet -v " + file)
+ ensure
+ #if FileTest.exists? file
+ # File.unlink(file)
+ #end
+ end
+ else
+ puts text
+ end
+ end
+
+ setup do
+ Puppet::Util::Log.newdestination(:console)
+
+ # Now parse the config
+ Puppet.parse_config
+
+ if options[:debug]
+ Puppet::Util::Log.level = :debug
+ elsif options[:verbose]
+ Puppet::Util::Log.level = :info
+ end
+ end
+end
diff --git a/spec/unit/application/ralsh.rb b/spec/unit/application/ralsh.rb
new file mode 100644
index 000000000..8f3951447
--- /dev/null
+++ b/spec/unit/application/ralsh.rb
@@ -0,0 +1,230 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/application/ralsh'
+
+describe "ralsh" do
+ before :each do
+ @ralsh = Puppet::Application[:ralsh]
+ end
+
+ it "should ask Puppet::Application to not parse Puppet configuration file" do
+ @ralsh.should_parse_config?.should be_false
+ end
+
+ it "should declare a main command" do
+ @ralsh.should respond_to(:main)
+ end
+
+ it "should declare a host option" do
+ @ralsh.should respond_to(:handle_host)
+ end
+
+ it "should declare a types option" do
+ @ralsh.should respond_to(:handle_types)
+ end
+
+ it "should declare a param option" do
+ @ralsh.should respond_to(:handle_param)
+ end
+
+ it "should declare a preinit block" do
+ @ralsh.should respond_to(:run_preinit)
+ end
+
+ describe "in preinit" do
+ it "should set hosts to nil" do
+ @ralsh.run_preinit
+
+ @ralsh.host.should be_nil
+ end
+
+ it "should init extra_params to empty array" do
+ @ralsh.run_preinit
+
+ @ralsh.extra_params.should == []
+ end
+ end
+
+ describe "when handling options" do
+
+ [:debug, :verbose, :edit].each do |option|
+ it "should declare handle_#{option} method" do
+ @ralsh.should respond_to("handle_#{option}".to_sym)
+ end
+
+ it "should store argument value when calling handle_#{option}" do
+ @ralsh.options.expects(:[]=).with(option, 'arg')
+ @ralsh.send("handle_#{option}".to_sym, 'arg')
+ end
+ end
+
+ it "should set options[:host] to given host" do
+ @ralsh.handle_host(:whatever)
+
+ @ralsh.host.should == :whatever
+ end
+
+ it "should load an display all types with types option" do
+ type1 = stub_everything 'type1', :name => :type1
+ type2 = stub_everything 'type2', :name => :type2
+ Puppet::Type.stubs(:loadall)
+ Puppet::Type.stubs(:eachtype).multiple_yields(type1,type2)
+ @ralsh.stubs(:exit)
+
+ @ralsh.expects(:puts).with(['type1','type2'])
+ @ralsh.handle_types(nil)
+ end
+
+ it "should add param to extra_params list" do
+ @ralsh.extra_params = [ :param1 ]
+ @ralsh.handle_param("whatever")
+
+ @ralsh.extra_params.should == [ :param1, :whatever ]
+ end
+ end
+
+ describe "during setup" do
+ before :each do
+ Puppet::Log.stubs(:newdestination)
+ Puppet::Log.stubs(:level=)
+ Puppet.stubs(:parse_config)
+ end
+
+
+ it "should set console as the log destination" do
+ Puppet::Log.expects(:newdestination).with(:console)
+
+ @ralsh.run_setup
+ end
+
+ it "should set log level to debug if --debug was passed" do
+ @ralsh.options.stubs(:[]).with(:debug).returns(true)
+
+ Puppet::Log.expects(:level=).with(:debug)
+
+ @ralsh.run_setup
+ end
+
+ it "should set log level to info if --verbose was passed" do
+ @ralsh.options.stubs(:[]).with(:debug).returns(false)
+ @ralsh.options.stubs(:[]).with(:verbose).returns(true)
+
+ Puppet::Log.expects(:level=).with(:info)
+
+ @ralsh.run_setup
+ end
+
+ it "should Parse puppet config" do
+ Puppet.expects(:parse_config)
+
+ @ralsh.run_setup
+ end
+ end
+
+ describe "when running" do
+
+ before :each do
+ @type = stub_everything 'type', :properties => []
+ ARGV.stubs(:shift).returns("type")
+ ARGV.stubs(:length).returns(1).then.returns(0)
+ Puppet::Type.stubs(:type).returns(@type)
+ end
+
+ it "should raise an error if no type is given" do
+ ARGV.stubs(:length).returns(0)
+
+ lambda { @ralsh.main }.should raise_error
+ end
+
+ it "should raise an error when editing a remote host" do
+ @ralsh.options.stubs(:[]).with(:edit).returns(true)
+ @ralsh.host = 'host'
+
+ lambda { @ralsh.main }.should raise_error
+ end
+
+ it "should raise an error if the type is not found" do
+ Puppet::Type.stubs(:type).returns(nil)
+
+ lambda { @ralsh.main }.should raise_error
+ end
+
+ describe "with a host" do
+ before :each do
+ @ralsh.stubs(:puts)
+ @ralsh.host = 'host'
+ @client = stub_everything 'client'
+ @client.stubs(:read_cert).returns(true)
+ @client.stubs(:instances).returns([])
+ Puppet::Network::Client.resource.stubs(:new).returns(@client)
+ end
+
+ it "should connect to it" do
+ Puppet::Network::Client.resource.expects(:new).with { |h| h[:Server] == 'host' }.returns(@client)
+ @ralsh.main
+ end
+
+ it "should raise an error if there are no certs" do
+ @client.stubs(:read_cert).returns(nil)
+
+ lambda { @ralsh.main }.should raise_error
+ end
+
+ it "should retrieve all the instances if there is no name" do
+ @client.expects(:instances).returns([])
+
+ @ralsh.main
+ end
+
+ it "should describe the given resource" do
+ ARGV.stubs(:shift).returns("type").then.returns('name')
+ ARGV.stubs(:length).returns(1).then.returns(1).then.returns(0)
+ @client.expects(:describe).returns(stub_everything)
+
+ @ralsh.main
+ end
+ end
+
+ describe "without a host" do
+ before :each do
+ @ralsh.stubs(:puts)
+ @ralsh.host = nil
+ end
+
+ it "should retrieve all the instances if there is no name" do
+ @type.expects(:instances).returns([])
+
+ @ralsh.main
+ end
+
+ describe 'but with a given name' do
+ before :each do
+ ARGV.stubs(:shift).returns("type").then.returns('name')
+ ARGV.stubs(:length).returns(1).then.returns(1).then.returns(0)
+ @object = stub_everything 'object', :to_trans => stub_everything('transportable')
+ @type.stubs(:create).returns(@object)
+ @object.stubs(:retrieve)
+ end
+
+ it "should retrieve a specific instace" do
+ @type.expects(:create).returns(@object)
+ @object.expects(:retrieve)
+
+ @ralsh.main
+ end
+
+ it "should add given parameters to object" do
+ ARGV.stubs(:each).yields('param=temp')
+ ARGV.stubs(:length).returns(1).then.returns(1).then.returns(1)
+ Puppet::Resource::Catalog.stubs(:new).returns(stub_everything)
+ @object.expects(:[]=).with('param','temp')
+
+ @ralsh.main
+ end
+ end
+ end
+
+ end
+end