diff --git a/bin/pi b/bin/pi index 5416e693f..0b700a2d0 100755 --- a/bin/pi +++ b/bin/pi @@ -1,234 +1,234 @@ -#!/usr/bin/ruby +#!/usr/bin/env ruby # # = Synopsis # # Print help about puppet types on the console. Run with '-h' to get detailed # help. # # FIXME: (1) Formatting could be a lot prettier # (2) The command line options are kinda screwy; unclear how best to # present the various pieces of info to user require 'puppet' require 'optparse' class Formatter def initialize(width) @width = width end def wrap(txt, opts) return "" unless txt && !txt.empty? work = (opts[:scrub] ? scrub(txt) : txt) indent = (opts[:indent] ? opts[:indent] : 0) textLen = @width - indent patt = Regexp.new("^(.{0,#{textLen}})[ \n]") prefix = " " * indent res = [] while work.length > textLen if work =~ patt res << $1 work.slice!(0, $&.length) else res << work.slice!(0, textLen) end end res << work if work.length.nonzero? return prefix + res.join("\n" + prefix) end def header(txt, sep = "-") "\n#{txt}\n" + sep * txt.size end private def scrub(text) # For text with no carriage returns, there's nothing to do. if text !~ /\n/ return text end indent = nil # If we can match an indentation, then just remove that same level of # indent from every line. if text =~ /^(\s+)/ indent = $1 return text.gsub(/^#{indent}/,'') else return text end end end class TypeDoc def initialize @format = Formatter.new(76) @types = {} Puppet::Type.loadall Puppet::Type.eachtype { |type| next if type.name == :component @types[type.name] = type } end def list_types puts "These are the types known to puppet:\n" @types.keys.sort { |a, b| a.to_s <=> b.to_s }.each do |name| type = @types[name] s = type.doc.gsub(/\s+/, " ") n = s.index(".") if n.nil? s = ".. no documentation .." elsif n > 45 s = s[0, 45] + " ..." else s = s[0, n] end printf "%-15s - %s\n", name, s end end def format_type(name, opts) name = name.to_sym unless @types.has_key?(name) puts "Unknown type #{name}" return end type = @types[name] puts @format.header(name.to_s, "=") puts @format.wrap(type.doc, :indent => 0, :scrub => true) + "\n\n" puts @format.header("Parameters") if opts[:parameters] format_attrs(type, [:property, :param]) else list_attrs(type, [:property, :param]) end if opts[:metaparams] puts @format.header("Meta Parameters") if opts[:parameters] format_attrs(type, [:meta]) else list_attrs(type, [:meta]) end end if type.providers.size > 0 puts @format.header("Providers") if opts[:providers] format_providers(type) else list_providers(type) end end end # List details about attributes def format_attrs(type, attrs) docs = {} type.eachattr do |obj, kind| if attrs.include?(kind) && obj.name != :provider docs[obj.name] = obj.doc end end docs.sort { |a,b| a[0].to_s <=> b[0].to_s }.each { |name, doc| print "\n- **%s**" % name if type.namevar == name and name != :name puts " (*namevar*)" else puts "" end puts @format.wrap(doc, :indent => 4, :scrub => true) } end # List the names of attributes def list_attrs(type, attrs) params = [] type.eachattr do |obj, kind| if attrs.include?(kind) && obj.name != :provider params << obj.name.to_s end end puts @format.wrap(params.sort.join(", "), :indent => 4) end def format_providers(type) type.providers.sort { |a,b| a.to_s <=> b.to_s }.each { |prov| puts "\n- **%s**" % prov puts @format.wrap(type.provider(prov).doc, :indent => 4, :scrub => true) } end def list_providers(type) list = type.providers.sort { |a,b| a.to_s <=> b.to_s }.join(", ") puts @format.wrap(list, :indent => 4) end end def process_args result = { :list => false, :providers => false, :parameters => true, :metaparams => false } opts = OptionParser.new("#{$0} [options] [type]") opts.separator(" Print documentation for puppet types and their parameters") opts.on("-l", "--list", "List all types") do |val| result[:list] = true end opts.on("-p", "--providers", "Describe providers in detail") do |val| result[:providers] = true end opts.on("-s", "--short", "Only list parameters without detail") do |val| result[:parameters] = false end opts.on("-m", "--meta", "Include metaparams") do |val| result[:metaparams] = true end result[:types] = opts.order(ARGV) # Check for obviously bogus options unless result[:list] || result[:types].size > 0 $stderr.puts opts exit(1) end if result[:list] && result[:types].size > 0 $stderr.puts "Warning: ignoring types when listing all types" end return result end opts = process_args doc = TypeDoc.new if opts[:list] doc.list_types else opts[:types].each { |name| doc.format_type(name, opts) } end diff --git a/bin/ralsh b/bin/ralsh index fdf64916f..1d0036717 100755 --- a/bin/ralsh +++ b/bin/ralsh @@ -1,270 +1,270 @@ -#!/usr/bin/ruby +#!/usr/bin/env ruby # vim: softtabstop=4 shiftwidth=4 expandtab # # = Synopsis # # Use the Puppet RAL to directly interact with the system. # # = Usage # # ralsh [-h|--help] [-d|--debug] [-v|--verbose] [-e|--edit] [-H|--host ] # [-p|--param ] [-t|--types] type # # = Description # # This command provides simple facilities for converting current system state # into Puppet code, along with some ability to use Puppet to affect the current # state. # # By default, you must at least provide a type to list, which case ralsh # will tell you everything it knows about all instances of that type. You can # optionally specify an instance name, and ralsh will only describe that single # instance. # # You can also add +--edit+ as an argument, and ralsh will write its output # to a file, open that file in an editor, and then apply the file as a Puppet # transaction. You can easily use this to use Puppet to make simple changes to # a system. # # = Options # # Note that any configuration parameter that's valid in the configuration file # is also a valid long argument. For example, 'ssldir' is a valid configuration # parameter, so you can specify '--ssldir ' as an argument. # # See the configuration file documentation at # http://reductivelabs.com/projects/puppet/reference/configref.html for # the full list of acceptable parameters. A commented list of all # configuration options can also be generated by running puppet with # '--genconfig'. # # debug:: # Enable full debugging. # # edit: # Write the results of the query to a file, open the file in an editor, # and read the file back in as an executable Puppet manifest. # # host: # When specified, connect to the resource server on the named host # and retrieve the list of resouces of the type specified. # # help: # Print this help message. # # param: # Add more parameters to be outputted from queries. # # types: # List all available types. # # verbose:: # Print extra information. # # = Example # # This example uses ``ralsh`` to return Puppet configuration for the user ``luke``:: # # $ ralsh user luke # user { 'luke': # home => '/home/luke', # uid => '100', # ensure => 'present', # comment => 'Luke Kanies,,,', # gid => '1000', # shell => '/bin/bash', # groups => ['sysadmin','audio','video','puppet'] # } # # = Author # # Luke Kanies # # = Copyright # # 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 == "" or value == [] 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::Node::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 diff --git a/lib/puppet/dsl.rb b/lib/puppet/dsl.rb index 966feaf9b..714b350f8 100644 --- a/lib/puppet/dsl.rb +++ b/lib/puppet/dsl.rb @@ -1,275 +1,275 @@ # Just quick mess-around to see what a DSL would look like. # # This is what the executable could look like: -##!/usr/bin/ruby +##!/usr/bin/env ruby # #require 'puppet' #require 'puppet/dsl' # #Puppet::DSL.import(ARGV[0]) # #bucket = Puppet::TransBucket.new #bucket.type = "top" #bucket.keyword = "class" # #Puppet::DSL.find_all do |name, sub| # sub.included #end.each do |name, sub| # bucket.push sub.export #end # #puts bucket.to_manifest # # And here's what an example config could look like: # -##!/usr/bin/ruby +##!/usr/bin/env ruby # # # require 'puppet' # require 'puppet/dsl' # # include Puppet::DSL # init() # # aspect :webserver do # file "/tmp/testone", :content => "yaytest" # # exec "testing", :command => "/bin/echo this is a test" # end # # aspect :other, :inherits => :webserver do # file "/tmp/testone", :mode => "755" # end # # acquire :other # # apply require 'puppet' # Provide the actual commands for acting like a language. module Puppet::DSL def aspect(name, options = {}, &block) Puppet::DSL::Aspect.new(name, options, &block) end def acquire(*names) names.each do |name| if aspect = Puppet::DSL::Aspect[name] unless aspect.evaluated? aspect.evaluate end else raise "Could not find aspect %s" % name end end end def apply bucket = export() catalog = bucket.to_catalog catalog.apply end def export objects = Puppet::DSL::Aspect.collect do |name, aspect| if aspect.evaluated? aspect.export end end.reject { |a| a.nil? }.flatten.collect do |obj| obj.to_trans end bucket = Puppet::TransBucket.new(objects) bucket.name = "top" bucket.type = "class" return bucket end def init unless Process.uid == 0 Puppet[:confdir] = File.expand_path("~/.puppet") Puppet[:vardir] = File.expand_path("~/.puppet/var") end Puppet[:user] = Process.uid Puppet[:group] = Process.gid Puppet::Util::Log.newdestination(:console) Puppet::Util::Log.level = :info end class Aspect Resource = Puppet::Parser::Resource include Puppet::Util include Puppet::DSL extend Puppet::Util extend Enumerable attr_accessor :parent, :name, :evaluated @aspects = {} @@objects = Hash.new do |hash, key| hash[key] = {} end # Create an instance method for every type Puppet::Type.loadall Puppet::Type.eachtype do |type| define_method(type.name) do |*args| newresource(type, *args) end end def self.[]=(name, aspect) name = symbolize(name) @aspects[name] = aspect end def self.[](name) name = symbolize(name) # Make sure there's always a main. This can get deleted in testing. if name == :main and ! @aspects[name] new(:main) {} end @aspects[name] end def self.clear @aspects.clear @@objects.clear end def self.delete(name) name = symbolize(name) if @aspects.has_key?(name) @aspects.delete(name) end end def self.each @aspects.each do |name, a| yield name, a end end def child_of?(aspect) unless aspect.is_a?(self.class) obj = self.class[aspect] unless obj raise "Could not find aspect %s" % aspect end aspect = obj end if self.parent if self.parent == aspect return true elsif self.parent.child_of?(aspect) return true else return false end else return false end end def evaluate if self.parent and ! self.parent.evaluated? self.parent.evaluate end unless evaluated? if defined? @block instance_eval(&@block) end @evaluated = true end end def evaluated? if self.evaluated true else false end end def export @resources.dup end def initialize(name, options = {}, &block) name = symbolize(name) @name = name if block @block = block end if pname = options[:inherits] if pname.is_a?(self.class) @parent = pname elsif parent = self.class[pname] @parent = parent else raise "Could not find parent aspect %s" % pname end end @resources = [] self.class[name] = self end def newresource(type, name, params = {}) if self.is_a?(Puppet::DSL::Aspect) source = self else source = Puppet::DSL::Aspect[:main] end unless obj = @@objects[type][name] obj = Resource.new :title => name, :type => type.name, :source => source, :scope => scope @@objects[type][name] = obj @resources << obj end params.each do |name, value| param = Resource::Param.new( :name => name, :value => value, :source => source ) obj.send(:set_parameter, param) end obj end def scope unless defined?(@scope) # Set the code to something innocuous; we just need the # scopes, not the interpreter. Hackish, but true. Puppet[:code] = " " @interp = Puppet::Parser::Interpreter.new require 'puppet/node' @node = Puppet::Node.new(Facter.value(:hostname)) if env = Puppet[:environment] and env == "" env = nil end @node.parameters = Facter.to_hash @compile = Puppet::Parser::Compiler.new(@node, @interp.send(:parser, env)) @scope = @compile.topscope end @scope end def type self.name end end end @aspects = {} diff --git a/spec/unit/file_serving/configuration.rb b/spec/unit/file_serving/configuration.rb index eecaefe5f..a0710e20d 100755 --- a/spec/unit/file_serving/configuration.rb +++ b/spec/unit/file_serving/configuration.rb @@ -1,224 +1,224 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/file_serving/configuration' describe Puppet::FileServing::Configuration do it "should make :new a private method" do proc { Puppet::FileServing::Configuration.new }.should raise_error end it "should return the same configuration each time :create is called" do Puppet::FileServing::Configuration.create.should equal(Puppet::FileServing::Configuration.create) end it "should have a method for removing the current configuration instance" do old = Puppet::FileServing::Configuration.create Puppet::FileServing::Configuration.clear_cache Puppet::FileServing::Configuration.create.should_not equal(old) end after do Puppet::FileServing::Configuration.clear_cache end end describe Puppet::FileServing::Configuration do before :each do @path = "/path/to/configuration/file.conf" Puppet.settings.stubs(:value).with(:fileserverconfig).returns(@path) end after :each do Puppet::FileServing::Configuration.clear_cache end describe Puppet::FileServing::Configuration, " when initializing" do it "should work without a configuration file" do FileTest.stubs(:exists?).with(@path).returns(false) proc { Puppet::FileServing::Configuration.create }.should_not raise_error end it "should parse the configuration file if present" do FileTest.stubs(:exists?).with(@path).returns(true) @parser = mock 'parser' @parser.expects(:parse).returns({}) Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser) Puppet::FileServing::Configuration.create end it "should determine the path to the configuration file from the Puppet settings" do Puppet::FileServing::Configuration.create end end describe Puppet::FileServing::Configuration, " when parsing the configuration file" do before do FileTest.stubs(:exists?).with(@path).returns(true) @parser = mock 'parser' Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser) end it "should set the mount list to the results of parsing" do @parser.expects(:parse).returns("one" => mock("mount")) config = Puppet::FileServing::Configuration.create config.mounted?("one").should be_true end it "should not raise exceptions" do @parser.expects(:parse).raises(ArgumentError) proc { Puppet::FileServing::Configuration.create }.should_not raise_error end it "should replace the existing mount list with the results of reparsing" do @parser.expects(:parse).returns("one" => mock("mount")) config = Puppet::FileServing::Configuration.create config.mounted?("one").should be_true # Now parse again @parser.expects(:parse).returns("two" => mock('other')) config.send(:readconfig, false) config.mounted?("one").should be_false config.mounted?("two").should be_true end it "should not replace the mount list until the file is entirely parsed successfully" do @parser.expects(:parse).returns("one" => mock("mount")) @parser.expects(:parse).raises(ArgumentError) config = Puppet::FileServing::Configuration.create # Now parse again, so the exception gets thrown config.send(:readconfig, false) config.mounted?("one").should be_true end end describe Puppet::FileServing::Configuration, " when finding files" do before do @parser = mock 'parser' @parser.stubs(:changed?).returns true FileTest.stubs(:exists?).with(@path).returns(true) Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser) @mount1 = stub 'mount', :name => "one" @mounts = {"one" => @mount1} Facter.stubs(:value).with("hostname").returns("whatever") @config = Puppet::FileServing::Configuration.create end it "should fail if the uri does not match a leading slash followed by a valid mount name" do @parser.expects(:parse).returns(@mounts) proc { @config.file_path("something") }.should raise_error(ArgumentError) end it "should use the first term after the first slash for the mount name" do @parser.expects(:parse).returns(@mounts) FileTest.stubs(:exists?).returns(true) @mount1.expects(:file) @config.file_path("/one") end it "should use the remainder of the URI after the mount name as the file name" do @parser.expects(:parse).returns(@mounts) @mount1.expects(:file).with("something/else", {}) FileTest.stubs(:exists?).returns(true) @config.file_path("/one/something/else") end it "should treat a bare name as a mount and no relative file" do @parser.expects(:parse).returns(@mounts) @mount1.expects(:file).with(nil, {}) FileTest.stubs(:exists?).returns(true) @config.file_path("/one") end it "should treat a name with a trailing slash equivalently to a name with no trailing slash" do @parser.expects(:parse).returns(@mounts) @mount1.expects(:file).with(nil, {}) FileTest.stubs(:exists?).returns(true) @config.file_path("/one/") end it "should return nil if the mount cannot be found" do @parser.expects(:changed?).returns(true) @parser.expects(:parse).returns({}) @config.file_path("/one/something").should be_nil end it "should return nil if the mount does not contain the file" do @parser.expects(:parse).returns(@mounts) @mount1.expects(:file).with("something/else", {}).returns(nil) @config.file_path("/one/something/else").should be_nil end it "should return the fully qualified path if the mount exists" do @parser.expects(:parse).returns(@mounts) @mount1.expects(:file).with("something/else", {}).returns("/full/path") @config.file_path("/one/something/else").should == "/full/path" end it "should reparse the configuration file when it has changed" do @mount1.stubs(:file).returns("whatever") @parser.expects(:changed?).returns(true) @parser.expects(:parse).returns(@mounts) FileTest.stubs(:exists?).returns(true) @config.file_path("/one/something") @parser.expects(:changed?).returns(true) @parser.expects(:parse).returns({}) @config.file_path("/one/something").should be_nil end end describe Puppet::FileServing::Configuration, " when checking authorization" do before do @parser = mock 'parser' @parser.stubs(:changed?).returns true FileTest.stubs(:exists?).with(@path).returns(true) Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser) @mount1 = stub 'mount', :name => "one" @mounts = {"one" => @mount1} @parser.stubs(:parse).returns(@mounts) Facter.stubs(:value).with("hostname").returns("whatever") @config = Puppet::FileServing::Configuration.create end it "should return false if the mount cannot be found" do @config.authorized?("/nope/my/file").should be_false end it "should use the mount to determine authorization" do @mount1.expects(:allowed?) @config.authorized?("/one/my/file") end it "should pass the client's name to the mount if provided" do @mount1.expects(:allowed?).with("myhost", nil) @config.authorized?("/one/my/file", :node => "myhost") end it "should pass the client's IP to the mount if provided" do @mount1.expects(:allowed?).with("myhost", "myip") @config.authorized?("/one/my/file", :node => "myhost", :ipaddress => "myip") end it "should return true if the mount allows the client" do @mount1.expects(:allowed?).returns(true) @config.authorized?("/one/my/file").should be_true end it "should return false if the mount denies the client" do @mount1.expects(:allowed?).returns(false) @config.authorized?("/one/my/file").should be_false end end -end \ No newline at end of file +end diff --git a/spec/unit/file_serving/configuration/parser.rb b/spec/unit/file_serving/configuration/parser.rb index df2f629d5..93d30ca1c 100755 --- a/spec/unit/file_serving/configuration/parser.rb +++ b/spec/unit/file_serving/configuration/parser.rb @@ -1,135 +1,135 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../../spec_helper' require 'puppet/file_serving/configuration/parser' describe Puppet::FileServing::Configuration::Parser do it "should subclass the LoadedFile class" do Puppet::FileServing::Configuration::Parser.superclass.should equal(Puppet::Util::LoadedFile) end end module FSConfigurationParserTesting def mock_file_content(content) # We want an array, but we actually want our carriage returns on all of it. lines = content.split("\n").collect { |l| l + "\n" } @filehandle.stubs(:each).multiple_yields(*lines) end end describe Puppet::FileServing::Configuration::Parser do before :each do @path = "/my/config.conf" FileTest.stubs(:exists?).with(@path).returns(true) FileTest.stubs(:readable?).with(@path).returns(true) @filehandle = mock 'filehandle' File.expects(:open).with(@path).yields(@filehandle) @parser = Puppet::FileServing::Configuration::Parser.new(@path) end describe Puppet::FileServing::Configuration::Parser, " when parsing" do include FSConfigurationParserTesting before do @parser.stubs(:add_modules_mount) end it "should allow comments" do @filehandle.expects(:each).yields("# this is a comment\n") proc { @parser.parse }.should_not raise_error end it "should allow blank lines" do @filehandle.expects(:each).yields("\n") proc { @parser.parse }.should_not raise_error end it "should create a new mount for each section in the configuration" do mount1 = mock 'one' mount2 = mock 'two' Puppet::FileServing::Mount.expects(:new).with("one").returns(mount1) Puppet::FileServing::Mount.expects(:new).with("two").returns(mount2) mock_file_content "[one]\n[two]\n" @parser.parse end # This test is almost the exact same as the previous one. it "should return a hash of the created mounts" do mount1 = mock 'one' mount2 = mock 'two' Puppet::FileServing::Mount.expects(:new).with("one").returns(mount1) Puppet::FileServing::Mount.expects(:new).with("two").returns(mount2) mock_file_content "[one]\n[two]\n" @parser.parse.should == {"one" => mount1, "two" => mount2} end it "should only allow mount names that are alphanumeric plus dashes" do mock_file_content "[a*b]\n" proc { @parser.parse }.should raise_error(ArgumentError) end it "should fail if the value for path/allow/deny starts with an equals sign" do mock_file_content "[one]\npath = /testing" proc { @parser.parse }.should raise_error(ArgumentError) end end describe Puppet::FileServing::Configuration::Parser, " when parsing mount attributes" do include FSConfigurationParserTesting before do @mount = stub 'mount', :name => "one" Puppet::FileServing::Mount.expects(:new).with("one").returns(@mount) @parser.stubs(:add_modules_mount) end it "should set the mount path to the path attribute from that section" do mock_file_content "[one]\npath /some/path\n" @mount.expects(:path=).with("/some/path") @parser.parse end it "should tell the mount to allow any allow values from the section" do mock_file_content "[one]\nallow something\n" @mount.expects(:info) @mount.expects(:allow).with("something") @parser.parse end it "should tell the mount to deny any deny values from the section" do mock_file_content "[one]\ndeny something\n" @mount.expects(:info) @mount.expects(:deny).with("something") @parser.parse end it "should fail on any attributes other than path, allow, and deny" do mock_file_content "[one]\ndo something\n" proc { @parser.parse }.should raise_error(ArgumentError) end end describe Puppet::FileServing::Configuration::Parser, " when parsing the modules mount" do include FSConfigurationParserTesting before do @mount = stub 'mount', :name => "modules" Puppet::FileServing::Mount.expects(:new).with("modules").returns(@mount) end it "should warn if a path is set" do mock_file_content "[modules]\npath /some/path\n" @modules.expects(:path=).never Puppet.expects(:warning) @parser.parse end end -end \ No newline at end of file +end diff --git a/spec/unit/indirector/checksum/file.rb b/spec/unit/indirector/checksum/file.rb index 4f8ee98b2..3a82faccc 100755 --- a/spec/unit/indirector/checksum/file.rb +++ b/spec/unit/indirector/checksum/file.rb @@ -1,140 +1,140 @@ #!/usr/bin/env ruby # # Created by Luke Kanies on 2007-9-22. # Copyright (c) 2007. All rights reserved. require File.dirname(__FILE__) + '/../../../spec_helper' require 'puppet/indirector/checksum/file' describe Puppet::Checksum::File do it "should be a subclass of the File terminus class" do Puppet::Checksum::File.superclass.should equal(Puppet::Indirector::File) end it "should have documentation" do Puppet::Checksum::File.doc.should be_instance_of(String) end end describe Puppet::Checksum::File, " when initializing" do it "should use the filebucket settings section" do Puppet.settings.expects(:use).with(:filebucket) Puppet::Checksum::File.new end end describe Puppet::Checksum::File do before :each do Puppet.settings.stubs(:use) @store = Puppet::Checksum::File.new @value = "70924d6fa4b2d745185fa4660703a5c0" @sum = stub 'sum', :name => @value @dir = "/what/ever" Puppet.stubs(:[]).with(:bucketdir).returns(@dir) @path = @store.path(@value) end describe Puppet::Checksum::File, " when determining file paths" do # I was previously passing the object in. it "should use the value passed in to path() as the checksum" do @value.expects(:name).never @store.path(@value) end it "should use the value of the :bucketdir setting as the root directory" do @path.should =~ %r{^#{@dir}} end it "should choose a path 8 directories deep with each directory name being the respective character in the checksum" do dirs = @value[0..7].split("").join(File::SEPARATOR) @path.should be_include(dirs) end it "should use the full checksum as the final directory name" do File.basename(File.dirname(@path)).should == @value end it "should use 'contents' as the actual file name" do File.basename(@path).should == "contents" end it "should use the bucketdir, the 8 sum character directories, the full checksum, and 'contents' as the full file name" do @path.should == [@dir, @value[0..7].split(""), @value, "contents"].flatten.join(File::SEPARATOR) end end describe Puppet::Checksum::File, " when retrieving files" do # The smallest test that will use the calculated path it "should look for the calculated path" do File.expects(:exist?).with(@path).returns(false) @store.find(@value) end it "should return an instance of Puppet::Checksum created with the content if the file exists" do content = "my content" sum = stub 'file' Puppet::Checksum.expects(:new).with(content).returns(sum) File.expects(:exist?).with(@path).returns(true) File.expects(:read).with(@path).returns(content) @store.find(@value).should equal(sum) end it "should return nil if no file is found" do File.expects(:exist?).with(@path).returns(false) @store.find(@value).should be_nil end it "should fail intelligently if a found file cannot be read" do File.expects(:exist?).with(@path).returns(true) File.expects(:read).with(@path).raises(RuntimeError) proc { @store.find(@value) }.should raise_error(Puppet::Error) end end describe Puppet::Checksum::File, " when saving files" do # LAK:FIXME I don't know how to include in the spec the fact that we're # using the superclass's save() method and thus are acquiring all of # it's behaviours. it "should save the content to the calculated path" do File.stubs(:directory?).with(File.dirname(@path)).returns(true) File.expects(:open).with(@path, "w") file = stub 'file', :name => @value @store.save(file) end it "should make any directories necessary for storage" do FileUtils.expects(:mkdir_p).with do |arg| File.umask == 0007 and arg == File.dirname(@path) end File.expects(:directory?).with(File.dirname(@path)).returns(true) File.expects(:open).with(@path, "w") file = stub 'file', :name => @value @store.save(file) end end describe Puppet::Checksum::File, " when deleting files" do it "should remove the file at the calculated path" do File.expects(:exist?).with(@path).returns(true) File.expects(:unlink).with(@path) file = stub 'file', :name => @value @store.destroy(file) end end -end \ No newline at end of file +end diff --git a/spec/unit/indirector/direct_file_server.rb b/spec/unit/indirector/direct_file_server.rb index 9f3652536..a89b938e7 100755 --- a/spec/unit/indirector/direct_file_server.rb +++ b/spec/unit/indirector/direct_file_server.rb @@ -1,92 +1,92 @@ #!/usr/bin/env ruby # # Created by Luke Kanies on 2007-10-24. # Copyright (c) 2007. All rights reserved. require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/indirector/direct_file_server' describe Puppet::Indirector::DirectFileServer do before :each do Puppet::Indirector::Terminus.stubs(:register_terminus_class) @model = mock 'model' @indirection = stub 'indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection) @direct_file_class = Class.new(Puppet::Indirector::DirectFileServer) do def self.to_s "Testing::Mytype" end end @server = @direct_file_class.new @uri = "file:///my/local" end describe Puppet::Indirector::DirectFileServer, "when finding a single file" do it "should return nil if the file does not exist" do FileTest.expects(:exists?).with("/my/local").returns false @server.find(@uri).should be_nil end it "should return a Content instance created with the full path to the file if the file exists" do FileTest.expects(:exists?).with("/my/local").returns true @model.expects(:new).returns(:mycontent) @server.find(@uri).should == :mycontent end end describe Puppet::Indirector::DirectFileServer, "when creating the instance for a single found file" do before do @data = mock 'content' @data.stubs(:collect_attributes) FileTest.expects(:exists?).with("/my/local").returns true end it "should create the Content instance with the original key as the key" do @model.expects(:new).with { |key, options| key == @uri }.returns(@data) @server.find(@uri) end it "should pass the full path to the instance" do @model.expects(:new).with { |key, options| options[:path] == "/my/local" }.returns(@data) @server.find(@uri) end it "should pass the :links setting on to the created Content instance if the file exists and there is a value for :links" do @model.expects(:new).returns(@data) @data.expects(:links=).with(:manage) @server.find(@uri, :links => :manage) end end describe Puppet::Indirector::DirectFileServer, "when searching for multiple files" do it "should return nil if the file does not exist" do FileTest.expects(:exists?).with("/my/local").returns false @server.find(@uri).should be_nil end it "should pass the original key to :path2instances" do FileTest.expects(:exists?).with("/my/local").returns true @server.expects(:path2instances).with { |uri, path, options| uri == @uri } @server.search(@uri) end it "should use :path2instances from the terminus_helper to return instances if the file exists" do FileTest.expects(:exists?).with("/my/local").returns true @server.expects(:path2instances) @server.search(@uri) end it "should pass any options on to :path2instances" do FileTest.expects(:exists?).with("/my/local").returns true @server.expects(:path2instances).with { |uri, path, options| options == {:testing => :one, :other => :two}} @server.search(@uri, :testing => :one, :other => :two) end end -end \ No newline at end of file +end diff --git a/spec/unit/indirector/facts/facter.rb b/spec/unit/indirector/facts/facter.rb index 0974a60ec..5ec66555d 100755 --- a/spec/unit/indirector/facts/facter.rb +++ b/spec/unit/indirector/facts/facter.rb @@ -1,76 +1,76 @@ #!/usr/bin/env ruby # # Created by Luke Kanies on 2007-9-23. # Copyright (c) 2007. All rights reserved. require File.dirname(__FILE__) + '/../../../spec_helper' require 'puppet/indirector/facts/facter' describe Puppet::Node::Facts::Facter do it "should be a subclass of the Code terminus" do Puppet::Node::Facts::Facter.superclass.should equal(Puppet::Indirector::Code) end it "should have documentation" do Puppet::Node::Facts::Facter.doc.should_not be_nil end it "should be registered with the configuration store indirection" do indirection = Puppet::Indirector::Indirection.instance(:facts) Puppet::Node::Facts::Facter.indirection.should equal(indirection) end it "should have its name set to :facter" do Puppet::Node::Facts::Facter.name.should == :facter end it "should load facts on initialization" do Puppet::Node::Facts::Facter.expects(:loadfacts) Puppet::Node::Facts::Facter.new end end describe Puppet::Node::Facts::Facter do before :each do @facter = Puppet::Node::Facts::Facter.new Facter.stubs(:to_hash).returns({}) @name = "me" @facts = @facter.find(@name) end describe Puppet::Node::Facts::Facter, " when finding facts" do it "should return a Facts instance" do @facts.should be_instance_of(Puppet::Node::Facts) end it "should return a Facts instance with the provided key as the name" do @facts.name.should == @name end it "should return the Facter facts as the values in the Facts instance" do Facter.expects(:to_hash).returns("one" => "two") facts = @facter.find(@name) facts.values["one"].should == "two" end end describe Puppet::Node::Facts::Facter, " when saving facts" do it "should fail" do proc { @facter.save(@facts) }.should raise_error(Puppet::DevError) end end describe Puppet::Node::Facts::Facter, " when destroying facts" do it "should fail" do proc { @facter.destroy(@facts) }.should raise_error(Puppet::DevError) end end describe Puppet::Node::Facts::Facter, " when loading facts from the factpath" do it "should load every fact in each factpath directory" end -end \ No newline at end of file +end diff --git a/spec/unit/indirector/file.rb b/spec/unit/indirector/file.rb index 37740f0d0..a2aa4502d 100755 --- a/spec/unit/indirector/file.rb +++ b/spec/unit/indirector/file.rb @@ -1,158 +1,158 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/indirector/file' describe Puppet::Indirector::File do before :each do Puppet::Indirector::Terminus.stubs(:register_terminus_class) @model = mock 'model' @indirection = stub 'indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection) @file_class = Class.new(Puppet::Indirector::File) do def self.to_s "Testing::Mytype" end end @searcher = @file_class.new @path = "/my/file" @dir = "/my" end describe Puppet::Indirector::File, " when finding files" do it "should provide a method to return file contents at a specified path" do @searcher.should respond_to(:find) end it "should return file contents as an instance of the model" do content = "my content" file = mock 'file' @model.expects(:new).with(content).returns(file) File.expects(:exist?).with(@path).returns(true) File.expects(:read).with(@path).returns(content) @searcher.find(@path) end it "should create the model instance with the content as the only argument to initialization" do content = "my content" file = mock 'file' @model.expects(:new).with(content).returns(file) File.expects(:exist?).with(@path).returns(true) File.expects(:read).with(@path).returns(content) @searcher.find(@path).should equal(file) end it "should return nil if no file is found" do File.expects(:exist?).with(@path).returns(false) @searcher.find(@path).should be_nil end it "should fail intelligently if a found file cannot be read" do File.expects(:exist?).with(@path).returns(true) File.expects(:read).with(@path).raises(RuntimeError) proc { @searcher.find(@path) }.should raise_error(Puppet::Error) end it "should use the path() method to calculate the path if it exists" do @searcher.meta_def(:path) do |name| name.upcase end File.expects(:exist?).with(@path.upcase).returns(false) @searcher.find(@path) end end describe Puppet::Indirector::File, " when saving files" do it "should provide a method to save file contents at a specified path" do filehandle = mock 'file' content = "my content" File.expects(:directory?).with(@dir).returns(true) File.expects(:open).with(@path, "w").yields(filehandle) filehandle.expects(:print).with(content) file = stub 'file', :content => content, :path => @path, :name => @path @searcher.save(file) end it "should fail intelligently if the file's parent directory does not exist" do File.expects(:directory?).with(@dir).returns(false) file = stub 'file', :path => @path, :name => @path proc { @searcher.save(file) }.should raise_error(Puppet::Error) end it "should fail intelligently if a file cannot be written" do filehandle = mock 'file' content = "my content" File.expects(:directory?).with(@dir).returns(true) File.expects(:open).with(@path, "w").yields(filehandle) filehandle.expects(:print).with(content).raises(ArgumentError) file = stub 'file', :content => content, :path => @path, :name => @path proc { @searcher.save(file) }.should raise_error(Puppet::Error) end it "should use the path() method to calculate the path if it exists" do @searcher.meta_def(:path) do |name| name.upcase end file = stub 'file', :name => "/yay" File.expects(:open).with("/YAY", "w") @searcher.save(file) end end describe Puppet::Indirector::File, " when removing files" do it "should provide a method to remove files at a specified path" do file = stub 'file', :path => @path, :name => @path File.expects(:exist?).with(@path).returns(true) File.expects(:unlink).with(@path) @searcher.destroy(file) end it "should throw an exception if the file is not found" do file = stub 'file', :path => @path, :name => @path File.expects(:exist?).with(@path).returns(false) proc { @searcher.destroy(file) }.should raise_error(Puppet::Error) end it "should fail intelligently if the file cannot be removed" do file = stub 'file', :path => @path, :name => @path File.expects(:exist?).with(@path).returns(true) File.expects(:unlink).with(@path).raises(ArgumentError) proc { @searcher.destroy(file) }.should raise_error(Puppet::Error) end it "should use the path() method to calculate the path if it exists" do @searcher.meta_def(:path) do |name| name.upcase end file = stub 'file', :name => "/yay" File.expects(:exist?).with("/YAY").returns(true) File.expects(:unlink).with("/YAY") @searcher.destroy(file) end end -end \ No newline at end of file +end diff --git a/spec/unit/indirector/file_server.rb b/spec/unit/indirector/file_server.rb index 974b95e0e..79be8cc29 100755 --- a/spec/unit/indirector/file_server.rb +++ b/spec/unit/indirector/file_server.rb @@ -1,168 +1,168 @@ #!/usr/bin/env ruby # # Created by Luke Kanies on 2007-10-19. # Copyright (c) 2007. All rights reserved. require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/indirector/file_server' require 'puppet/file_serving/configuration' describe Puppet::Indirector::FileServer do before :each do Puppet::Indirector::Terminus.stubs(:register_terminus_class) @model = mock 'model' @indirection = stub 'indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection) @file_server_class = Class.new(Puppet::Indirector::FileServer) do def self.to_s "Testing::Mytype" end end @file_server = @file_server_class.new @uri = "puppetmounts://host/my/local/file" @configuration = mock 'configuration' Puppet::FileServing::Configuration.stubs(:create).returns(@configuration) end describe Puppet::Indirector::FileServer, " when finding files" do it "should use the path portion of the URI as the file name" do @configuration.expects(:file_path).with("/my/local/file", :node => nil) @file_server.find(@uri) end it "should use the FileServing configuration to convert the file name to a fully qualified path" do @configuration.expects(:file_path).with("/my/local/file", :node => nil) @file_server.find(@uri) end it "should pass the node name to the FileServing configuration if one is provided" do @configuration.expects(:file_path).with("/my/local/file", :node => "testing") @file_server.find(@uri, :node => "testing") end it "should return nil if no fully qualified path is found" do @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns(nil) @file_server.find(@uri).should be_nil end it "should return an instance of the model created with the full path if a file is found" do @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns("/some/file") @model.expects(:new).returns(:myinstance) @file_server.find(@uri).should == :myinstance end end describe Puppet::Indirector::FileServer, " when returning instances" do before :each do @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns("/some/file") @instance = mock 'instance' end it "should create the instance with the key used to find the instance" do @model.expects(:new).with { |key, *options| key == @uri } @file_server.find(@uri) end it "should create the instance with the path at which the instance was found" do @model.expects(:new).with { |key, options| options[:path] == "/some/file" } @file_server.find(@uri) end it "should set the provided :links setting on to the instance if one is provided" do @model.expects(:new).returns(@instance) @instance.expects(:links=).with(:mytest) @file_server.find(@uri, :links => :mytest) end it "should not set a :links value if no :links parameter is provided" do @model.expects(:new).returns(@instance) @file_server.find(@uri) end end describe Puppet::Indirector::FileServer, " when checking authorization" do it "should have an authorization hook" do @file_server.should respond_to(:authorized?) end it "should deny the :destroy method" do @file_server.authorized?(:destroy, "whatever").should be_false end it "should deny the :save method" do @file_server.authorized?(:save, "whatever").should be_false end it "should use the file server configuration to determine authorization" do @configuration.expects(:authorized?) @file_server.authorized?(:find, "puppetmounts://host/my/file") end it "should pass the file path from the URI to the file server configuration" do @configuration.expects(:authorized?).with { |uri, *args| uri == "/my/file" } @file_server.authorized?(:find, "puppetmounts://host/my/file") end it "should pass the node name to the file server configuration" do @configuration.expects(:authorized?).with { |key, options| options[:node] == "mynode" } @file_server.authorized?(:find, "puppetmounts://host/my/file", :node => "mynode") end it "should pass the IP address to the file server configuration" do @configuration.expects(:authorized?).with { |key, options| options[:ipaddress] == "myip" } @file_server.authorized?(:find, "puppetmounts://host/my/file", :ipaddress => "myip") end it "should return false if the file server configuration denies authorization" do @configuration.expects(:authorized?).returns(false) @file_server.authorized?(:find, "puppetmounts://host/my/file").should be_false end it "should return true if the file server configuration approves authorization" do @configuration.expects(:authorized?).returns(true) @file_server.authorized?(:find, "puppetmounts://host/my/file").should be_true end end describe Puppet::Indirector::FileServer, " when searching for files" do it "should use the path portion of the URI as the file name" do @configuration.expects(:file_path).with("/my/local/file", :node => nil) @file_server.search(@uri) end it "should use the FileServing configuration to convert the file name to a fully qualified path" do @configuration.expects(:file_path).with("/my/local/file", :node => nil) @file_server.search(@uri) end it "should pass the node name to the FileServing configuration if one is provided" do @configuration.expects(:file_path).with("/my/local/file", :node => "testing") @file_server.search(@uri, :node => "testing") end it "should return nil if no fully qualified path is found" do @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns(nil) @file_server.search(@uri).should be_nil end it "should use :path2instances from the terminus_helper to return instances if a module is found and the file exists" do @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns("/my/file") @file_server.expects(:path2instances).with(@uri, "/my/file", {}) @file_server.search(@uri) end it "should pass any options on to :path2instances" do @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns("/my/file") @file_server.expects(:path2instances).with(@uri, "/my/file", :testing => :one, :other => :two) @file_server.search(@uri, :testing => :one, :other => :two) end end -end \ No newline at end of file +end diff --git a/spec/unit/parser/ast/node.rb b/spec/unit/parser/ast/node.rb index 757934415..aaba4c2e8 100755 --- a/spec/unit/parser/ast/node.rb +++ b/spec/unit/parser/ast/node.rb @@ -1,125 +1,125 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../../spec_helper' describe Puppet::Parser::AST::Node do before :each do @node = Puppet::Node.new "testnode" @parser = Puppet::Parser::Parser.new :environment => "development" @scope_resource = stub 'scope_resource', :builtin? => true @compiler = Puppet::Parser::Compiler.new(@node, @parser) @scope = @compiler.topscope end describe Puppet::Parser::AST::Node, "when evaluating" do before do @top = @parser.newnode("top").shift @middle = @parser.newnode("middle", :parent => "top").shift end it "should create a resource that references itself" do @top.evaluate(@scope) @compiler.catalog.resource(:node, "top").should be_an_instance_of(Puppet::Parser::Resource) end it "should evaluate the parent class if one exists" do @middle.evaluate(@scope) @compiler.catalog.resource(:node, "top").should be_an_instance_of(Puppet::Parser::Resource) end it "should fail to evaluate if a parent class is defined but cannot be found" do othertop = @parser.newnode("something", :parent => "yay").shift lambda { othertop.evaluate(@scope) }.should raise_error(Puppet::ParseError) end it "should not create a new resource if one already exists" do @compiler.catalog.expects(:resource).with(:node, "top").returns("something") @compiler.catalog.expects(:add_resource).never @top.evaluate(@scope) end it "should not create a new parent resource if one already exists and it has a parent class" do @top.evaluate(@scope) top_resource = @compiler.catalog.resource(:node, "top") @middle.evaluate(@scope) @compiler.catalog.resource(:node, "top").should equal(top_resource) end # #795 - tag before evaluation. it "should tag the catalog with the resource tags when it is evaluated" do @middle.evaluate(@scope) @compiler.catalog.should be_tagged("middle") end it "should tag the catalog with the parent class tags when it is evaluated" do @middle.evaluate(@scope) @compiler.catalog.should be_tagged("top") end end describe Puppet::Parser::AST::Node, "when evaluating code" do before do @top_resource = stub "top_resource" @top = @parser.newnode("top", :code => @top_resource).shift @middle_resource = stub "middle_resource" @middle = @parser.newnode("middle", :parent => "top", :code => @middle_resource).shift end it "should evaluate the code referred to by the class" do @top_resource.expects(:safeevaluate) resource = @top.evaluate(@scope) @top.evaluate_code(resource) end it "should evaluate the parent class's code if it has a parent" do @top_resource.expects(:safeevaluate) @middle_resource.expects(:safeevaluate) resource = @middle.evaluate(@scope) @middle.evaluate_code(resource) end it "should not evaluate the parent class's code if the parent has already been evaluated" do @top_resource.stubs(:safeevaluate) resource = @top.evaluate(@scope) @top.evaluate_code(resource) @top_resource.expects(:safeevaluate).never @middle_resource.stubs(:safeevaluate) resource = @middle.evaluate(@scope) @middle.evaluate_code(resource) end it "should use the parent class's scope as its parent scope" do @top_resource.stubs(:safeevaluate) @middle_resource.stubs(:safeevaluate) resource = @middle.evaluate(@scope) @middle.evaluate_code(resource) @compiler.class_scope(@middle).parent.should equal(@compiler.class_scope(@top)) end it "should add the parent class's namespace to its namespace search path" do @top_resource.stubs(:safeevaluate) @middle_resource.stubs(:safeevaluate) resource = @middle.evaluate(@scope) @middle.evaluate_code(resource) @compiler.class_scope(@middle).namespaces.should be_include(@top.namespace) end end -end \ No newline at end of file +end diff --git a/spec/unit/ral/provider/mount/parsed.rb b/spec/unit/ral/provider/mount/parsed.rb index b2ca22987..21276d911 100755 --- a/spec/unit/ral/provider/mount/parsed.rb +++ b/spec/unit/ral/provider/mount/parsed.rb @@ -1,185 +1,185 @@ #!/usr/bin/env ruby # # Created by Luke Kanies on 2007-9-12. # Copyright (c) 2006. All rights reserved. require File.dirname(__FILE__) + '/../../../../spec_helper' require 'puppettest/support/utils' require 'puppettest/fileparsing' module ParsedMountTesting include PuppetTest::Support::Utils include PuppetTest::FileParsing def fake_fstab os = Facter['operatingsystem'] if os == "Solaris" name = "solaris.fstab" elsif os == "FreeBSD" name = "freebsd.fstab" else # Catchall for other fstabs name = "linux.fstab" end oldpath = @provider_class.default_target return fakefile(File::join("data/types/mount", name)) end def mkmountargs mount = nil if defined? @pcount @pcount += 1 else @pcount = 1 end args = { :name => "/fspuppet%s" % @pcount, :device => "/dev/dsk%s" % @pcount, } @provider_class.fields(:parsed).each do |field| unless args.include? field args[field] = "fake%s%s" % [field, @pcount] end end return args end def mkmount hash = mkmountargs() #hash[:provider] = @provider_class.name fakeresource = stub :type => :mount, :name => hash[:name] fakeresource.stubs(:[]).with(:name).returns(hash[:name]) fakeresource.stubs(:should).with(:target).returns(nil) mount = @provider_class.new(fakeresource) hash[:record_type] = :parsed hash[:ensure] = :present mount.property_hash = hash return mount end # Here we just create a fake host type that answers to all of the methods # but does not modify our actual system. def mkfaketype @provider.stubs(:filetype).returns(Puppet::Util::FileType.filetype(:ram)) end end provider_class = Puppet::Type.type(:mount).provider(:parsed) describe provider_class do before :each do @mount_class = Puppet.type(:mount) @provider_class = @mount_class.provider(:parsed) end describe provider_class do include ParsedMountTesting it "should be able to parse all of the example mount tabs" do tab = fake_fstab @provider = @provider_class # LAK:FIXME Again, a relatively bad test, but I don't know how to rspec-ify this. # I suppose this is more of an integration test? I dunno. fakedataparse(tab) do # Now just make we've got some mounts we know will be there hashes = @provider_class.target_records(tab).find_all { |i| i.is_a? Hash } (hashes.length > 0).should be_true root = hashes.find { |i| i[:name] == "/" } proc { @provider_class.to_file(hashes) }.should_not raise_error end end # LAK:FIXME I can't mock Facter because this test happens at parse-time. it "should default to /etc/vfstab on Solaris and /etc/fstab everywhere else" do should = case Facter.value(:operatingsystem) when "Solaris": "/etc/vfstab" else "/etc/fstab" end Puppet::Type.type(:mount).provider(:parsed).default_target.should == should end end describe provider_class, " when mounting an absent filesystem" do include ParsedMountTesting # #730 - Make sure 'flush' is called when a mount is moving from absent to mounted it "should flush the fstab to disk" do mount = mkmount # Mark the mount as absent mount.property_hash[:ensure] = :absent mount.stubs(:mountcmd) # just so we don't actually try to mount anything mount.expects(:flush) mount.mount end end describe provider_class, " when modifying the filesystem tab" do include ParsedMountTesting before do @mount = mkmount @target = @provider_class.default_target # Never write to disk, only to RAM. @provider_class.stubs(:filetype).returns(Puppet::Util::FileType.filetype(:ram)) end it "should write the mount to disk when :flush is called" do @mount.flush text = @provider_class.target_object(@provider_class.default_target).read text.should == @mount.class.to_line(@mount.property_hash) + "\n" end end describe provider_class, " when parsing information about the root filesystem" do confine "Mount type not tested on Darwin" => Facter["operatingsystem"].value != "Darwin" include ParsedMountTesting before do @mount = @mount_class.create :name => "/" @provider = @mount.provider end it "should have a filesystem tab" do FileTest.should be_exist(@provider_class.default_target) end it "should find the root filesystem" do @provider_class.prefetch("/" => @mount) @mount.provider.property_hash[:ensure].should == :present end it "should determine that the root fs is mounted" do @provider_class.prefetch("/" => @mount) @mount.provider.should be_mounted end after do Puppet::Type.allclear end end describe provider_class, " when mounting and unmounting" do include ParsedMountTesting it "should call the 'mount' command to mount the filesystem" it "should call the 'unmount' command to unmount the filesystem" it "should specify the filesystem when remounting a filesystem" end -end \ No newline at end of file +end diff --git a/spec/unit/ral/type/mount.rb b/spec/unit/ral/type/mount.rb index 9247601e6..8fa2e6f7c 100755 --- a/spec/unit/ral/type/mount.rb +++ b/spec/unit/ral/type/mount.rb @@ -1,192 +1,192 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../../spec_helper' require 'puppet/type/mount' describe Puppet::Type::Mount do it "should have a :refreshable feature that requires the :remount method" do Puppet::Type::Mount.provider_feature(:refreshable).methods.should == [:remount] end it "should have no default value for :ensure" do mount = Puppet::Type::Mount.create(:name => "yay") mount.should(:ensure).should be_nil end after { Puppet::Type::Mount.clear } end describe Puppet::Type::Mount, "when validating attributes" do [:name, :remounts].each do |param| it "should have a #{param} parameter" do Puppet::Type::Mount.attrtype(param).should == :param end end [:ensure, :device, :blockdevice, :fstype, :options, :pass, :dump, :atboot, :target].each do |param| it "should have a #{param} property" do Puppet::Type::Mount.attrtype(param).should == :property end end end describe Puppet::Type::Mount::Ensure, "when validating values" do before do @provider = stub 'provider', :class => Puppet::Type::Mount.defaultprovider, :clear => nil Puppet::Type::Mount.defaultprovider.expects(:new).returns(@provider) end it "should support :present as a value to :ensure" do Puppet::Type::Mount.create(:name => "yay", :ensure => :present) end it "should alias :unmounted to :present as a value to :ensure" do mount = Puppet::Type::Mount.create(:name => "yay", :ensure => :unmounted) mount.should(:ensure).should == :present end it "should support :absent as a value to :ensure" do Puppet::Type::Mount.create(:name => "yay", :ensure => :absent) end it "should support :mounted as a value to :ensure" do Puppet::Type::Mount.create(:name => "yay", :ensure => :mounted) end after { Puppet::Type::Mount.clear } end describe Puppet::Type::Mount::Ensure do before :each do @provider = stub 'provider', :class => Puppet::Type::Mount.defaultprovider, :clear => nil, :satisfies? => true, :name => :mock Puppet::Type::Mount.defaultprovider.stubs(:new).returns(@provider) @mount = Puppet::Type::Mount.create(:name => "yay", :check => :ensure) @ensure = @mount.property(:ensure) end after :each do Puppet::Type::Mount.clear end def mount_stub(params) Puppet::Type::Mount.validproperties.each do |prop| unless params[prop] params[prop] = :absent @mount[prop] = :absent end end params.each do |param, value| @provider.stubs(param).returns(value) end end describe Puppet::Type::Mount::Ensure, "when retrieving its current state" do it "should return the provider's value if it is :absent" do @provider.expects(:ensure).returns(:absent) @ensure.retrieve.should == :absent end it "should return :mounted if the provider indicates it is mounted and the value is not :absent" do @provider.expects(:ensure).returns(:present) @provider.expects(:mounted?).returns(true) @ensure.retrieve.should == :mounted end it "should return :present if the provider indicates it is not mounted and the value is not :absent" do @provider.expects(:ensure).returns(:present) @provider.expects(:mounted?).returns(false) @ensure.retrieve.should == :present end end describe Puppet::Type::Mount::Ensure, "when changing the host" do it "should destroy itself if it should be absent" do @provider.stubs(:mounted?).returns(false) @provider.expects(:destroy) @ensure.should = :absent @ensure.sync end it "should unmount itself before destroying if it is mounted and should be absent" do @provider.expects(:mounted?).returns(true) @provider.expects(:unmount) @provider.expects(:destroy) @ensure.should = :absent @ensure.sync end it "should create itself if it is absent and should be present" do @provider.stubs(:mounted?).returns(false) @provider.expects(:create) @ensure.should = :present @ensure.sync end it "should unmount itself if it is mounted and should be present" do @provider.stubs(:mounted?).returns(true) # The interface here is just too much work to test right now. @ensure.stubs(:syncothers) @provider.expects(:unmount) @ensure.should = :present @ensure.sync end it "should create and mount itself if it does not exist and should be mounted" do @provider.stubs(:ensure).returns(:absent) @provider.stubs(:mounted?).returns(false) @provider.expects(:create) @ensure.stubs(:syncothers) @provider.expects(:mount) @ensure.should = :mounted @ensure.sync end it "should mount itself if it is present and should be mounted" do @provider.stubs(:ensure).returns(:present) @provider.stubs(:mounted?).returns(false) @ensure.stubs(:syncothers) @provider.expects(:mount) @ensure.should = :mounted @ensure.sync end it "should create but not mount itself if it is absent and mounted and should be mounted" do @provider.stubs(:ensure).returns(:absent) @provider.stubs(:mounted?).returns(true) @ensure.stubs(:syncothers) @provider.expects(:create) @ensure.should = :mounted @ensure.sync end end describe Puppet::Type::Mount, "when responding to events" do it "should remount if it is currently mounted" do @provider.expects(:mounted?).returns(true) @provider.expects(:remount) @mount.refresh end it "should not remount if it is not currently mounted" do @provider.expects(:mounted?).returns(false) @provider.expects(:remount).never @mount.refresh end it "should not remount swap filesystems" do @mount[:fstype] = "swap" @provider.expects(:remount).never @mount.refresh end end -end \ No newline at end of file +end diff --git a/test/lib/stubba.rb b/test/lib/stubba.rb index eade747f6..747054cfc 100644 --- a/test/lib/stubba.rb +++ b/test/lib/stubba.rb @@ -1,2 +1,2 @@ # for backwards compatibility -require 'mocha' \ No newline at end of file +require 'mocha'