diff options
author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-01-17 07:11:50 +0000 |
---|---|---|
committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-01-17 07:11:50 +0000 |
commit | 3700b37e2386e7dbaabd90b7ba13c3dce06203d2 (patch) | |
tree | 28a691598edd5e56332c0d8e254263fb4fe8a9f4 | |
parent | 92a780a3106f863e442c12897184abbe39fe3310 (diff) | |
download | puppet-3700b37e2386e7dbaabd90b7ba13c3dce06203d2.tar.gz puppet-3700b37e2386e7dbaabd90b7ba13c3dce06203d2.tar.xz puppet-3700b37e2386e7dbaabd90b7ba13c3dce06203d2.zip |
Adding an "ensure" state where appropriate, and significantly reworking the builtin docs.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@832 980ebf18-57e1-0310-9a29-db15c13687c0
68 files changed, 916 insertions, 441 deletions
@@ -52,12 +52,16 @@ task :default => :alltests task :u => :unittests task :a => :alltests -Rake::TestTask.new(:alltests) do |t| - t.test_files = FileList['test/*/*.rb'] - t.warning = true - t.verbose = false +task :alltests do + sh %{cd test; ./test} end +#Rake::TestTask.new(:alltests) do |t| +# t.test_files = FileList['test/*/*.rb'] +# t.warning = true +# t.verbose = false +#end + #Rake::TestTask.new(:unittests) do |t| # t.test_files = FileList['test/test'] # t.warning = true @@ -348,6 +352,9 @@ task :hosttest do out += %x{ssh #{host} 'cd puppet/test; sudo ./test' 2>&1} if $? != 0 + file = File.join("/tmp", "%stest.out" % host) + File.open(file, "w") { |of| of.print out } + puts "%s failed; output is in %s" % [host, file] puts out end #sh %{ssh #{host} 'cd #{cwd}/test; sudo ./test' 2>&1} diff --git a/bin/puppetdoc b/bin/puppetdoc index 4d4dba082..6ff42743b 100755 --- a/bin/puppetdoc +++ b/bin/puppetdoc @@ -45,17 +45,13 @@ rescue LoadError $haveusage = false end -def tab(num) - return $tab * num -end - result = GetoptLong.new( [ "--help", "-h", GetoptLong::NO_ARGUMENT ] ) debug = false -$tab = " " +$tab = " " begin result.each { |opt,arg| @@ -77,6 +73,33 @@ rescue GetoptLong::InvalidOption => detail exit(1) end +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 + +# Indent every line in the chunk except those which begin with '..'. +def indent(text, tab) + return text.gsub(/(^|\A)/, tab).gsub(/^ +\.\./, "..") +end + +#def tab(num) +# return $tab * num +#end + puts %{ ============== Type Reference @@ -93,6 +116,11 @@ puts %{ Meta-Parameters --------------- +Metaparameters are parameters that work with any element; they are part of the +Puppet framework itself rather than being part of the implementation of any +given instance. Thus, any defined metaparameter can be used with any instance +in your manifest, including defined components. + } begin params = [] @@ -104,10 +132,11 @@ begin a.to_s <=> b.to_s }.each { |param| puts "- **" + param.to_s + "**" - puts tab(1) + Puppet::Type.metaparamdoc(param).gsub(/\n\s*/,' ') + #puts tab(1) + Puppet::Type.metaparamdoc(param).scrub.indent($tab)gsub(/\n\s*/,' ') + puts indent(scrub(Puppet::Type.metaparamdoc(param)), $tab) } rescue => detail - puts "type %s had incorrect params: %s" % detail + puts "incorrect metaparams: %s" % detail exit(1) end @@ -118,9 +147,25 @@ Types - *namevar* is the parameter used to uniquely identify a type instance. This is the parameter that gets assigned when a string is provided before - the colon in a type declaration. -- *parameters* determine the specific configuration of the instance. + the colon in a type declaration. In general, only developers will need to + worry about which parameter is the ``namevar``. + + In the following code:: + file { "/etc/passwd": + owner => root, + group => root, + mode => 644 + } + + "/etc/passwd" is considered the name of the file object (used for things like + dependency handling), and because ``path`` is the namevar for ``file``, that + string is assigned to the ``path`` parameter. + +- *parameters* determine the specific configuration of the instance. They either + directly modify the system (internally, these are called states) or they affect + how the instance behaves (e.g., adding a search path for ``exec`` instances + or determining recursion on ``file`` instances). } @@ -141,8 +186,8 @@ types.sort { |a,b| %s" % [name, "=" * (name.to_s.length + 4)] #String.new('n%s\n') % name.to_s #puts "**" + type.doc.gsub(/\n\s*/, ' ') + "**\n\n" - puts type.doc.gsub(/\n\s*/, ' ') + "\n\n" - type.buildstatehash + puts scrub(type.doc) + "\n\n" + #puts tab(1) + "* namevar: %s" % type.namevar docs = {} #puts "%s States\n'''''''''''''''''''''''''''''''" % name.to_s.capitalize @@ -153,7 +198,33 @@ types.sort { |a,b| state.nodoc }.each { |sname| state = type.statebyname(sname) - docs[sname] = state.doc.gsub(/\n\s*/,' ') + + doc = nil + str = nil + unless doc = state.doc.dup + $stderr.puts "No docs for %s[%s]" % [type, sname] + next + end + str = doc + #puts "A---" + str + "---" + str = scrub(str) + #puts "B---" + str + "---" + #str = indent(str, $tab) + #puts "C---" + str + "---" + #str = indent($tab, scrub(doc)) + + # If the state has values, then add them: + + #if values = state.values + # unless values.empty? + # extra = "Acceptable values are %s." % values.join(", ") + # str += "\n\n#{extra}" + # end + #end + + str = indent(str, $tab) + #puts "---" + str + "---" + docs[sname] = str #puts "- **%s**" % sname #puts tab(1) + state.doc.gsub(/\n\s*/,' ') } @@ -162,7 +233,7 @@ types.sort { |a,b| type.parameters.sort { |a,b| a.to_s <=> b.to_s }.each { |name,param| - docs[name] = type.paramdoc(name).gsub(/\n\s*/,' ') + docs[name] = indent(scrub(type.paramdoc(name)), $tab) } docs.sort { |a, b| @@ -174,7 +245,7 @@ types.sort { |a,b| else puts "" end - puts tab(1) + doc + puts doc } puts "\n" } diff --git a/examples/code/allatonce b/examples/code/allatonce index 2857b9b62..8912ec4e7 100644 --- a/examples/code/allatonce +++ b/examples/code/allatonce @@ -1,7 +1,7 @@ # $Id$ define thingie { - file { "/tmp/classtest": create => true, mode => 755 } + file { "/tmp/classtest": ensure => file, mode => 755 } #testing {} } diff --git a/examples/code/classing b/examples/code/classing index 8f9477721..0eeb713b9 100644 --- a/examples/code/classing +++ b/examples/code/classing @@ -12,7 +12,7 @@ class base() { class server inherits base { file { "/tmp/puppetfiletest": - create => true + ensure => file } } diff --git a/examples/code/components b/examples/code/components index 15f131d0e..3da43c571 100644 --- a/examples/code/components +++ b/examples/code/components @@ -59,7 +59,7 @@ define sleeper(path,mode) { } $files = ["/tmp/testness","/tmp/funtest"] file { $files: - create => true + ensure => file } } diff --git a/examples/code/file.bl b/examples/code/file.bl index 41d80b53d..ef46ba223 100644 --- a/examples/code/file.bl +++ b/examples/code/file.bl @@ -1,11 +1,11 @@ # $Id$ file { - "/tmp/atest": create => true, mode => 755; - "/tmp/btest": create => true, mode => 755 + "/tmp/atest": ensure => file, mode => 755; + "/tmp/btest": ensure => file, mode => 755 } file { - "/tmp/ctest": create => true; - "/tmp/dtest": create => true; + "/tmp/ctest": ensure => file; + "/tmp/dtest": ensure => file; } diff --git a/examples/code/filedefaults b/examples/code/filedefaults index cb005c093..56cf76a9a 100644 --- a/examples/code/filedefaults +++ b/examples/code/filedefaults @@ -6,5 +6,5 @@ File { } file { "/tmp/filedefaultstest": - create => true + ensure => file } diff --git a/examples/code/relationships b/examples/code/relationships index f2319d5e4..795788947 100644 --- a/examples/code/relationships +++ b/examples/code/relationships @@ -8,7 +8,7 @@ $path = "../examples/root/etc/configfile" define files { file { "/tmp/yaytest": - create => true, + ensure => file, mode => 755 } file { "/tmp/exists": diff --git a/examples/code/simpletests b/examples/code/simpletests index 6a2d5c5ff..b4fd3234e 100644 --- a/examples/code/simpletests +++ b/examples/code/simpletests @@ -1,11 +1,11 @@ # $Id$ file { - "/tmp/atest": create => true; - "/tmp/btest": create => true + "/tmp/atest": ensure => file; + "/tmp/btest": ensure => file } file { - "/tmp/ctest": create => true; - "/tmp/dtest": create => true; + "/tmp/ctest": ensure => file; + "/tmp/dtest": ensure => file; } diff --git a/examples/code/snippets/argumentdefaults b/examples/code/snippets/argumentdefaults index b4081e9b0..7d814f2fb 100644 --- a/examples/code/snippets/argumentdefaults +++ b/examples/code/snippets/argumentdefaults @@ -1,7 +1,7 @@ # $Id$ define testargs(file, mode = 755) { - file { $file: create => true, mode => $mode } + file { $file: ensure => file, mode => $mode } } testargs { "testingname": diff --git a/examples/code/snippets/casestatement b/examples/code/snippets/casestatement index 565b8b422..05ac031e6 100644 --- a/examples/code/snippets/casestatement +++ b/examples/code/snippets/casestatement @@ -4,10 +4,10 @@ $var = "value" case $var { "nope": { - file { "/tmp/fakefile": mode => 644, create => true } + file { "/tmp/fakefile": mode => 644, ensure => file } } "value": { - file { "/tmp/existsfile": mode => 755, create => true } + file { "/tmp/existsfile": mode => 755, ensure => file } } } @@ -15,15 +15,15 @@ $ovar = "yayness" case $ovar { "fooness": { - file { "/tmp/nostillexistsfile": mode => 644, create => true } + file { "/tmp/nostillexistsfile": mode => 644, ensure => file } } "booness", "yayness": { case $var { "nep": { - file { "/tmp/noexistsfile": mode => 644, create => true } + file { "/tmp/noexistsfile": mode => 644, ensure => file } } "value": { - file { "/tmp/existsfile2": mode => 755, create => true } + file { "/tmp/existsfile2": mode => 755, ensure => file } } } } @@ -31,10 +31,10 @@ case $ovar { case $ovar { "fooness": { - file { "/tmp/nostillexistsfile": mode => 644, create => true } + file { "/tmp/nostillexistsfile": mode => 644, ensure => file } } default: { - file { "/tmp/existsfile3": mode => 755, create => true } + file { "/tmp/existsfile3": mode => 755, ensure => file } } } @@ -42,6 +42,6 @@ $bool = true case $bool { true: { - file { "/tmp/existsfile4": mode => 755, create => true } + file { "/tmp/existsfile4": mode => 755, ensure => file } } } diff --git a/examples/code/snippets/classheirarchy.pp b/examples/code/snippets/classheirarchy.pp index 3f9527573..36619d8b9 100644 --- a/examples/code/snippets/classheirarchy.pp +++ b/examples/code/snippets/classheirarchy.pp @@ -1,15 +1,15 @@ # $Id$ class base { - file { "/tmp/classheir1": create => true, mode => 755 } + file { "/tmp/classheir1": ensure => file, mode => 755 } } class sub1 inherits base { - file { "/tmp/classheir2": create => true, mode => 755 } + file { "/tmp/classheir2": ensure => file, mode => 755 } } class sub2 inherits base { - file { "/tmp/classheir3": create => true, mode => 755 } + file { "/tmp/classheir3": ensure => file, mode => 755 } } include sub1, sub2 diff --git a/examples/code/snippets/classincludes.pp b/examples/code/snippets/classincludes.pp index 3cf2bbd44..927800599 100644 --- a/examples/code/snippets/classincludes.pp +++ b/examples/code/snippets/classincludes.pp @@ -1,15 +1,15 @@ # $Id$ class base { - file { "/tmp/classincludes1": create => true, mode => 755 } + file { "/tmp/classincludes1": ensure => file, mode => 755 } } class sub1 inherits base { - file { "/tmp/classincludes2": create => true, mode => 755 } + file { "/tmp/classincludes2": ensure => file, mode => 755 } } class sub2 inherits base { - file { "/tmp/classincludes3": create => true, mode => 755 } + file { "/tmp/classincludes3": ensure => file, mode => 755 } } $sub = "sub2" diff --git a/examples/code/snippets/classpathtest b/examples/code/snippets/classpathtest index 07b9e5aea..68610958b 100644 --- a/examples/code/snippets/classpathtest +++ b/examples/code/snippets/classpathtest @@ -1,7 +1,7 @@ # $Id$ define component { - file { "/tmp/classtest": create => true, mode => 755 } + file { "/tmp/classtest": ensure => file, mode => 755 } } class testing { diff --git a/examples/code/snippets/dirchmod b/examples/code/snippets/dirchmod index 0a8268fa8..dc2cc8949 100644 --- a/examples/code/snippets/dirchmod +++ b/examples/code/snippets/dirchmod @@ -1,8 +1,8 @@ # $Id$ file { - "/tmp/dirchmodtesta": create => directory; - "/tmp/dirchmodtesta/testing": create => true + "/tmp/dirchmodtesta": ensure => directory; + "/tmp/dirchmodtesta/testing": ensure => file } file { "/tmp/dirchmodtesta": @@ -10,8 +10,8 @@ file { "/tmp/dirchmodtesta": } file { - "/tmp/dirchmodtestb": create => directory; - "/tmp/dirchmodtestb/testing": create => true + "/tmp/dirchmodtestb": ensure => directory; + "/tmp/dirchmodtestb/testing": ensure => file } file { "/tmp/dirchmodtestb": diff --git a/examples/code/snippets/failmissingexecpath.pp b/examples/code/snippets/failmissingexecpath.pp index 3f43be325..fe17b049b 100644 --- a/examples/code/snippets/failmissingexecpath.pp +++ b/examples/code/snippets/failmissingexecpath.pp @@ -1,6 +1,6 @@ define distloc(path) { file { "/tmp/exectesting1": - create => file + ensure => file } exec { "touch $path": subscribe => file["/tmp/exectesting1"], diff --git a/examples/code/snippets/falsevalues.pp b/examples/code/snippets/falsevalues.pp index 21f957bd2..2143b79a7 100644 --- a/examples/code/snippets/falsevalues.pp +++ b/examples/code/snippets/falsevalues.pp @@ -1,3 +1,3 @@ $value = false -file { "/tmp/falsevalues$value": create => true } +file { "/tmp/falsevalues$value": ensure => file } diff --git a/examples/code/snippets/filecreate b/examples/code/snippets/filecreate index 7a4cdbb1e..d7972c234 100644 --- a/examples/code/snippets/filecreate +++ b/examples/code/snippets/filecreate @@ -1,11 +1,11 @@ # $Id$ file { - "/tmp/createatest": create => true, mode => 755; - "/tmp/createbtest": create => true, mode => 755 + "/tmp/createatest": ensure => file, mode => 755; + "/tmp/createbtest": ensure => file, mode => 755 } file { - "/tmp/createctest": create => true; - "/tmp/createdtest": create => true; + "/tmp/createctest": ensure => file; + "/tmp/createdtest": ensure => file; } diff --git a/examples/code/snippets/implicititeration b/examples/code/snippets/implicititeration index c4a850a94..6f34cb29c 100644 --- a/examples/code/snippets/implicititeration +++ b/examples/code/snippets/implicititeration @@ -2,14 +2,14 @@ $files = ["/tmp/iterationatest", "/tmp/iterationbtest"] -file { $files: create => true, mode => 755 } +file { $files: ensure => file, mode => 755 } file { ["/tmp/iterationctest", "/tmp/iterationdtest"]: - create => true, + ensure => file, mode => 755 } file { - ["/tmp/iterationetest", "/tmp/iterationftest"]: create => true, mode => 755; - ["/tmp/iterationgtest", "/tmp/iterationhtest"]: create => true, mode => 755; + ["/tmp/iterationetest", "/tmp/iterationftest"]: ensure => file, mode => 755; + ["/tmp/iterationgtest", "/tmp/iterationhtest"]: ensure => file, mode => 755; } diff --git a/examples/code/snippets/multipleinstances b/examples/code/snippets/multipleinstances index abc060316..2f9b3c2e8 100644 --- a/examples/code/snippets/multipleinstances +++ b/examples/code/snippets/multipleinstances @@ -1,7 +1,7 @@ # $Id$ file { - "/tmp/multipleinstancesa": create => true, mode => 755; - "/tmp/multipleinstancesb": create => true, mode => 755; - "/tmp/multipleinstancesc": create => true, mode => 755; + "/tmp/multipleinstancesa": ensure => file, mode => 755; + "/tmp/multipleinstancesb": ensure => file, mode => 755; + "/tmp/multipleinstancesc": ensure => file, mode => 755; } diff --git a/examples/code/snippets/namevartest b/examples/code/snippets/namevartest index 93a263dd4..b4db5bacf 100644 --- a/examples/code/snippets/namevartest +++ b/examples/code/snippets/namevartest @@ -1,9 +1,9 @@ -define filetest(mode, create = true) { +define filetest(mode, ensure = file) { file { $name: mode => $mode, - create => $create + ensure => $ensure } } filetest { "/tmp/testfiletest": mode => 644} -filetest { "/tmp/testdirtest": mode => 755, create => directory} +filetest { "/tmp/testdirtest": mode => 755, ensure => directory} diff --git a/examples/code/snippets/scopetest b/examples/code/snippets/scopetest index b00560372..3d3b31d8a 100644 --- a/examples/code/snippets/scopetest +++ b/examples/code/snippets/scopetest @@ -2,7 +2,7 @@ $mode = 640 define thing { - file { "/tmp/scopetest": create => true, mode => $mode } + file { "/tmp/scopetest": ensure => file, mode => $mode } } class testing { diff --git a/examples/code/snippets/selectorvalues.pp b/examples/code/snippets/selectorvalues.pp index e4d1ce444..dcbf16c70 100644 --- a/examples/code/snippets/selectorvalues.pp +++ b/examples/code/snippets/selectorvalues.pp @@ -17,6 +17,6 @@ $mode3 = $value3 ? { default => 644 } -file { "/tmp/selectorvalues1": create => true, mode => $mode1 } -file { "/tmp/selectorvalues2": create => true, mode => $mode2 } -file { "/tmp/selectorvalues3": create => true, mode => $mode3 } +file { "/tmp/selectorvalues1": ensure => file, mode => $mode1 } +file { "/tmp/selectorvalues2": ensure => file, mode => $mode2 } +file { "/tmp/selectorvalues3": ensure => file, mode => $mode3 } diff --git a/examples/code/snippets/simpledefaults b/examples/code/snippets/simpledefaults index a8f6190b1..63d199a68 100644 --- a/examples/code/snippets/simpledefaults +++ b/examples/code/snippets/simpledefaults @@ -2,4 +2,4 @@ File { mode => 755 } -file { "/tmp/defaulttest": create => true } +file { "/tmp/defaulttest": ensure => file } diff --git a/examples/code/snippets/simpleselector b/examples/code/snippets/simpleselector index 52a06c773..8b9bc7292 100644 --- a/examples/code/snippets/simpleselector +++ b/examples/code/snippets/simpleselector @@ -3,7 +3,7 @@ $var = "value" file { "/tmp/snippetselectatest": - create => true, + ensure => file, mode => $var ? { nottrue => 641, value => 755 @@ -11,7 +11,7 @@ file { "/tmp/snippetselectatest": } file { "/tmp/snippetselectbtest": - create => true, + ensure => file, mode => $var ? { nottrue => 644, default => 755 @@ -21,7 +21,7 @@ file { "/tmp/snippetselectbtest": $othervar = "complex value" file { "/tmp/snippetselectctest": - create => true, + ensure => file, mode => $othervar ? { "complex value" => 755, default => 644 @@ -30,7 +30,7 @@ file { "/tmp/snippetselectctest": $anothervar = Yayness file { "/tmp/snippetselectdtest": - create => true, + ensure => file, mode => $anothervar ? { Yayness => 755, default => 644 diff --git a/lib/puppet/parameter.rb b/lib/puppet/parameter.rb index 6f3b0f184..d6662ef1a 100644 --- a/lib/puppet/parameter.rb +++ b/lib/puppet/parameter.rb @@ -15,6 +15,12 @@ module Puppet end end + def nodefault + undef_method :default + #if defined_method? :default + #end + end + # Store documentation for this parameter. def desc(str) @doc = str diff --git a/lib/puppet/sslcertificates.rb b/lib/puppet/sslcertificates.rb index 9196da61b..6c21f7c49 100755 --- a/lib/puppet/sslcertificates.rb +++ b/lib/puppet/sslcertificates.rb @@ -28,7 +28,7 @@ module SSLCertificates obj = Puppet::Type.type(:file).create( :name => File.join(path), :mode => "750", - :create => "directory" + :ensure => "directory" ) comp.push obj diff --git a/lib/puppet/storage.rb b/lib/puppet/storage.rb index af59efa19..b174e0183 100644 --- a/lib/puppet/storage.rb +++ b/lib/puppet/storage.rb @@ -2,34 +2,32 @@ require 'yaml' module Puppet # a class for storing state - class Storage - include Singleton - - def initialize - self.class.load - end + class Storage + include Singleton + + def initialize + self.class.load + end def self.clear - @@state = nil + @@state.clear Storage.init end def self.init Puppet.debug "Initializing Storage" - @@state = Hash.new { |hash,key| - hash[key] = Hash.new(nil) - } + @@state = {} @@splitchar = "\t" end self.init - def self.load + def self.load if Puppet[:checksumfile].nil? raise Puppet::DevError, "Somehow the statefile is nil" end - unless File.exists?(Puppet[:checksumfile]) + unless File.exists?(Puppet[:checksumfile]) Puppet.info "Statefile %s does not exist" % Puppet[:checksumfile] unless defined? @@state and ! @@state.nil? self.init @@ -56,16 +54,22 @@ module Puppet } #Puppet.debug "Loaded state is %s" % @@state.inspect - end + end + + def self.stateinspect + @@state.inspect + end - def self.state(myclass) + def self.state(myclass) unless myclass.is_a? Class myclass = myclass.class end + + @@state[myclass.to_s] ||= {} return @@state[myclass.to_s] - end + end - def self.store + def self.store unless FileTest.directory?(File.dirname(Puppet[:checksumfile])) begin Puppet.recmkdir(File.dirname(Puppet[:checksumfile])) @@ -95,8 +99,8 @@ module Puppet # } #} } - end - end + end + end end # $Id$ diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb index 05da74d30..ca85f92aa 100644 --- a/lib/puppet/type.rb +++ b/lib/puppet/type.rb @@ -219,7 +219,7 @@ class Type < Puppet::Element self.newstate(:ensure, Puppet::State::Ensure, &block) else self.newstate(:ensure, Puppet::State::Ensure) do - # don't actually do anything with the block, but it's required... + self.defaultvalues end end end @@ -227,6 +227,10 @@ class Type < Puppet::Element # Return a Type instance by name. def self.type(name) @types ||= {} + + if name.is_a?(String) + name = name.intern + end @types[name] end @@ -1245,7 +1249,7 @@ class Type < Puppet::Element end if klass.method_defined?(:default) obj = self.newattr(type, klass) - self.info "defaulting %s to %s" % [obj.name, obj.default] + #self.debug "defaulting %s to %s" % [obj.name, obj.default] obj.value = obj.default end } @@ -1511,7 +1515,7 @@ class Type < Puppet::Element states.each { |state| unless state.insync? self.debug("%s is not in sync: %s vs %s" % - [state, state.is, state.should]) + [state, state.is.inspect, state.should.inspect]) insync = false end } @@ -1709,15 +1713,15 @@ class Type < Puppet::Element end # Add all of the meta parameters. - newmetaparam(:onerror) do - desc "How to handle errors -- roll back innermost - transaction, roll back entire transaction, ignore, etc. Currently - non-functional." - end + #newmetaparam(:onerror) do + # desc "How to handle errors -- roll back innermost + # transaction, roll back entire transaction, ignore, etc. Currently + # non-functional." + #end newmetaparam(:noop) do desc "Boolean flag indicating whether work should actually - be done." + be done. *true*/**false**" munge do |noop| if noop == "true" or noop == true return true @@ -1729,15 +1733,18 @@ class Type < Puppet::Element end end - newmetaparam(:schedule) do - desc "On what schedule the object should be managed. - Currently non-functional." - end + #newmetaparam(:schedule) do + # desc "On what schedule the object should be managed. + # Currently non-functional." + #end newmetaparam(:check) do desc "States which should have their values retrieved but which should not actually be modified. This is currently used - internally, but will eventually be used for querying." + internally, but will eventually be used for querying, so that you + could specify that you wanted to check the install state of all + packages, and then query the Puppet client daemon to get reports + on all packages." munge do |args| unless args.is_a?(Array) @@ -1764,7 +1771,37 @@ class Type < Puppet::Element newmetaparam(:require) do desc "One or more objects that this object depends on. This is used purely for guaranteeing that changes to required objects - happen before the dependent object." + happen before the dependent object. For instance:: + + # Create the destination directory before you copy things down + file { \"/usr/local/scripts\": + ensure => directory + } + + file { \"/usr/local/scripts/myscript\": + source => \"puppet://server/module/myscript\", + mode => 755, + require => file[\"/usr/local/scripts\"] + } + + Note that Puppet will autorequire everything that it can, and + there are hooks in place so that it's easy for elements to add new + ways to autorequire objects, so if you think Puppet could be + smarter here, let us know. + + In fact, the above code was redundant -- Puppet will autorequire + any parent directories that are being managed; it will + automatically realize that the parent directory should be created + before the script is pulled down. + + Currently, exec_ elements will autorequire their CWD (if it is + specified) plus any fully qualified paths that appear in the + command. For instance, if you had an ``exec`` command that ran + the ``myscript`` mentioned above, the above code that pulls the + file down would be automatically listed as a requirement to the + ``exec`` code, so that you would always be running againts the + most recent version. + " # Take whatever dependencies currently exist and add these. # Note that this probably doesn't behave correctly with unsubscribe. @@ -1788,9 +1825,22 @@ class Type < Puppet::Element # For each object we require, subscribe to all events that it generates. # We might reduce the level of subscription eventually, but for now... newmetaparam(:subscribe) do - desc "One or more objects that this object depends on. - Changes in the subscribed to objects result in the dependent objects being - refreshed (e.g., a service will get restarted)." + desc "One or more objects that this object depends on. Changes in the + subscribed to objects result in the dependent objects being + refreshed (e.g., a service will get restarted). For instance:: + + class nagios { + file { \"/etc/nagios/nagios.conf\": + source => \"puppet://server/module/nagios.conf\", + alias => nagconf # just to make things easier for me + } + + service { nagios: + running => true, + require => file[nagconf] + } + } + " munge do |requires| if values = @parent[:subscribe] @@ -1803,7 +1853,9 @@ class Type < Puppet::Element newmetaparam(:loglevel) do desc "Sets the level that information will be logged: - debug, info, verbose, notice, warning, err, alert, emerg or crit" + debug, info, verbose, notice, warning, err, alert, emerg or crit. + The log levels have the biggest impact when logs are sent to + syslog (which is currently the default)." defaultto :notice validate do |loglevel| @@ -1830,7 +1882,23 @@ class Type < Puppet::Element desc "Creates an alias for the object. This simplifies lookup of the object so is useful in the language. It is especially useful when you are creating long commands using exec or when many different - systems call a given package different names." + systems call a given package_ different names:: + + + file { \"/usr/local/scripts/myscript\": + source => \"puppet://server/module/myscript\", + mode => 755, + alias => myscript + } + + exec { \"/usr/local/scripts/myscript\": + require => file[myscript] + } + + Again, this is somewhat redundant, since any sane person would + just use a variable (unless the two statements were in different + scopes), and Puppet will autorequire the script anyway, but it + gets the point across." munge do |aliases| unless aliases.is_a?(Array) diff --git a/lib/puppet/type/cron.rb b/lib/puppet/type/cron.rb index c6acbfea0..03b27eef5 100755 --- a/lib/puppet/type/cron.rb +++ b/lib/puppet/type/cron.rb @@ -156,7 +156,12 @@ module Puppet newparam(:name) do desc "The symbolic name of the cron job. This name - is used for human reference only." + is used for human reference only and is generated + automatically for cron jobs found on the system. This generally + won't matter, as Puppet will do its best to match existing + cron jobs against specified jobs (and Puppet adds a tag to + cron jobs it adds), but it is at least possible that converting + from unmanaged jobs to managed jobs might require manual intervention." isnamevar end @@ -186,11 +191,23 @@ module Puppet and the user are optional, although specifying no periodic fields would result in the command being executed every minute. While the name of the cron job is not part of the actual - job, it is used by Puppet to store and retrieve it. If you specify - a cron job that matches an existing job in every way except name, - then the jobs will be considered equivalent and the new name will - be permanently associated with that job. Once this association is - made and synced to disk, you can then manage the job normally." + job, it is used by Puppet to store and retrieve it. + + If you specify a cron job that matches an existing job in every way + except name, then the jobs will be considered equivalent and the + new name will be permanently associated with that job. Once this + association is made and synced to disk, you can then manage the job + normally (e.g., change the schedule of the job). + + Example:: + + cron { logrotate: + command => \"/usr/sbin/logrotate\", + user => root, + hour => 2, + minute => 0 + } + " @instances = {} @tabs = {} diff --git a/lib/puppet/type/exec.rb b/lib/puppet/type/exec.rb index 9570c86b8..78f96d9a7 100755 --- a/lib/puppet/type/exec.rb +++ b/lib/puppet/type/exec.rb @@ -5,7 +5,7 @@ module Puppet harm, i.e., they are *idempotent*. One useful way to create idempotent commands is to use the *creates* parameter. - It is worth nothing that ``exec`` is special, in that it is not + It is worth noting that ``exec`` is special, in that it is not currently considered an error to have multiple ``exec`` instances with the same name. This was done purely because it had to be this way in order to get certain functionality, but it complicates things. @@ -13,7 +13,34 @@ module Puppet share their commands with other instances as a dependency, since Puppet has no way of knowing which instance you mean. - It is recommended to avoid duplicate names whenever possible." + For example:: + + # defined in the production class + exec { \"make\": + cwd => \"/prod/build/dir\" + } + + . etc. . + + # defined in the test class + exec { \"make\": + cwd => \"/test/build/dir\" + } + + Any other type would throw an error, complaining that you had + the same instance being managed in multiple places, but these are + obviously different images, so ``exec`` had to be treated specially. + + It is recommended to avoid duplicate names whenever possible. + + There is a strong tendency to use ``exec`` to do whatever work Puppet + can't already do; while this is obviously acceptable (and unavoidable) + in the short term, it is highly recommended to migrate work from ``exec`` + to real Puppet element types as quickly as possible. If you find that + you are doing a lot of work with ``exec``, please at least notify + us at Reductive Labs what you are doing, and hopefully we can work with + you to get a native element type for the work you are doing. In general, + it is a Puppet bug if you need ``exec`` to do your work." require 'open3' require 'puppet/type/state' @@ -27,7 +54,7 @@ module Puppet attr_reader :output desc "The expected return code. An error will be returned if the - executed command returns something else." + executed command returns something else. Defaults to 0." # Make output a bit prettier def change_to_s @@ -153,18 +180,24 @@ module Puppet newparam(:command) do isnamevar - desc "The actual command to execute." + desc "The actual command to execute. Must either be fully qualified + or a search path for the command must be provided. If the command + succeeds, any output produced will be logged at the instance's + normal log level (usually ``notice``), but if the command fails + (meaning its return code does not match the specified code) then + any output is logged at the ``err`` log level." end newparam(:path) do desc "The search path used for command execution. - Commands must be fully qualified if no path is specified." + Commands must be fully qualified if no path is specified. Paths + must be specified as an array, not as a colon-separated list." end newparam(:user) do desc "The user to run the command as. Note that if you use this then any error output is not currently captured. This - is mostly because of a bug within Ruby." + is because of a bug within Ruby." munge do |user| unless Process.uid == 0 @@ -192,7 +225,10 @@ module Puppet end newparam(:group) do - desc "The group to run the command as." + desc "The group to run the command as. This seems to work quite + haphazardly on different platforms -- it is a platform issue + not a Ruby or Puppet one, since the same variety exists when + running commnands as different users in the shell." # Execute the command as the specified group munge do |group| @@ -234,13 +270,39 @@ module Puppet newparam(:refreshonly) do desc "The command should only be run as a - refresh mechanism for when a dependent object is changed." + refresh mechanism for when a dependent object is changed. It only + makes sense to use this option when this command depends on some + other object; it is useful for triggering an action:: + + # Pull down the main aliases file + file { \"/etc/aliases\": + source => \"puppet://server/module/aliases\" + } + + # Rebuild the database, but only when the file changes + exec { newaliases: + path => [\"/usr/bin\", \"/usr/sbin\"], + require => file[\"/etc/aliases\"], + refreshonly => true + } + + " end newparam(:creates) do desc "A file that this command creates. If this parameter is provided, then the command will only be run - if the specified file does not exist." + if the specified file does not exist. + + :: + + exec { \"tar xf /my/tar/file.tar\": + cwd => \"/var/tmp\", + creates => \"/var/tmp/myfile\", + path => [\"/usr/bin\", \"/usr/sbin\"] + } + + " # FIXME if they try to set this and fail, then we should probably # fail the entire exec, right? diff --git a/lib/puppet/type/group.rb b/lib/puppet/type/group.rb index 2e4ad2441..4bb5f9d95 100755 --- a/lib/puppet/type/group.rb +++ b/lib/puppet/type/group.rb @@ -14,7 +14,14 @@ require 'puppet/type/nameservice' module Puppet newtype(:group, Puppet::Type::NSSType) do @doc = "Manage groups. This type can only create groups. Group - membership must be managed on individual users." + membership must be managed on individual users. This element type + uses the prescribed native tools for creating groups and generally + uses POSIX APIs for retrieving information about them. It does + not directly modify /etc/group or anything. + + For most platforms, the tools used are ``groupadd`` and its ilk; + for Mac OS X, NetInfo is used. This is currently unconfigurable, + but if you desperately need it to be so, please contact us." case Facter["operatingsystem"].value when "Darwin": diff --git a/lib/puppet/type/package.rb b/lib/puppet/type/package.rb index dd53c13ed..75bf04bfa 100644 --- a/lib/puppet/type/package.rb +++ b/lib/puppet/type/package.rb @@ -8,9 +8,17 @@ require 'puppet/type/state' module Puppet class PackageError < Puppet::Error; end newtype(:package) do - @doc = "Manage packages. Eventually will support retrieving packages - from remote sources but currently only supports packaging - systems which can retrieve their own packages, like ``apt``." + @doc = "Manage packages. There is a basic dichotomy in package + support right now: Some package types (e.g., yum and apt) can + retrieve their own package files, while others (e.g., rpm and + sunpkg) cannot. For those package formats that cannot retrieve + their own files, you can use the ``source`` parameter to point to + the correct file. + + Puppet will automatically guess the packaging format that you are + using based on the platform you are on, but you can override it + using the ``type`` parameter; obviously, if you specify that you + want to use ``rpm`` then the ``rpm`` tools must be available." # Create a new packaging type def self.newpkgtype(name, parent = nil, &block) @@ -64,43 +72,57 @@ module Puppet end ensurable do - desc "What state the package should be in. Specifying *true* will - only result in a change if the package is not installed at all; - use *latest* to keep the package (and, depending on the package - system, its prerequisites) up to date. Specifying *false* will - uninstall the package if it is installed. - *true*/*false*/*latest*" - - munge do |value| - # possible values are: true, false, and a version number - case value - when "latest": - unless @parent.respond_to?(:latest) - self.err @parent.inspect - raise Puppet::Error, - "Package type %s cannot install later versions" % - @parent[:type].name - end - return :latest - when true, :present: - return :present - when false, :absent: - return :absent - else - # We allow them to set a should value however they want, - # but only specific package types will be able to use this - # value - return value - end + desc "What state the package should be in. The primary options + are *installed* (also called *present*), *uninstalled* (also + called *absent*), and *latest*. *latest* only makes sense for + those packaging formats that can retrieve new packages on + their own." + + #munge do |value| + # # possible values are: true, false, and a version number + # case value + # when "latest": + # unless @parent.respond_to?(:latest) + # self.err @parent.inspect + # raise Puppet::Error, + # "Package type %s cannot install later versions" % + # @parent[:type].name + # end + # return :latest + # when true, :present: + # return :present + # when false, :absent: + # return :absent + # else + # # We allow them to set a should value however they want, + # # but only specific package types will be able to use this + # # value + # return value + # end + #end + + newvalue(:present) do + @parent.install end - # Alias the 'present' value. - newvalue(:installed) do - self.set(:present) + newvalue(:absent) do + @parent.uninstall end + # Alias the 'present' value. + aliasvalue(:installed, :present) + #newvalue(:installed) do + # self.set(:present) + #end + newvalue(:latest) do @parent.update + + if self.is == :absent + return :package_created + else + return :package_changed + end end # Override the parent method, because we've got all kinds of @@ -168,12 +190,47 @@ module Puppet attr_reader :pkgtype newparam(:name) do - desc "The package name." + desc "The package name. This is the name that the packaging + system uses internally, which is sometimes (especially on Solaris) + a name that is basically useless to humans. If you want to + abstract package installation, then you can use aliases to provide + a common name to packages:: + + # In the 'openssl' class + $ssl = $operationgsystem ? { + solaris => SMCossl, + default => openssl + } + + # It is not an error to set an alias to the same value as the + # object name. + package { $ssl: + ensure => installed, + alias => openssl + } + + . etc. . + + $ssh = $operationgsystem ? { + solaris => SMCossh, + default => openssh + } + + # Use the alias to specify a dependency, rather than + # having another selector to figure it out again. + package { $ssh: + ensure => installed, + alias => openssh, + require => package[openssl] + } + + " isnamevar end newparam(:type) do - desc "The package format, e.g., rpm or dpkg." + desc "The package format. You will seldom need to specify this -- Puppet + will discover the appropriate format for your platform." defaultto { @parent.class.default } @@ -206,7 +263,10 @@ module Puppet # it almost seems like versions should be a read-only state, # supporting syncing only in certain cases. newparam(:version) do - desc "A read-only parameter set by the package." + desc "For some platforms this is a read-only parameter set by the + package, but for others, setting this parameter will cause + the package of that version to be installed. It just depends + on the features of the packaging system." # validate do |value| # unless @parent.respond_to?(:versionable?) and @parent.versionable? @@ -356,10 +416,6 @@ module Puppet end end - def create - self.install - end - # The 'query' method returns a hash of info if the package # exists and returns nil if it does not. def exists? diff --git a/lib/puppet/type/package/dpkg.rb b/lib/puppet/type/package/dpkg.rb index 9b76c6d92..97220d2fd 100755 --- a/lib/puppet/type/package/dpkg.rb +++ b/lib/puppet/type/package/dpkg.rb @@ -92,7 +92,7 @@ module Puppet return packages end - def destroy + def uninstall cmd = "dpkg -r %s" % self.name output = %x{#{cmd} 2>&1} if $? != 0 diff --git a/lib/puppet/type/package/rpm.rb b/lib/puppet/type/package/rpm.rb index cf1bb4534..cf84c3536 100755 --- a/lib/puppet/type/package/rpm.rb +++ b/lib/puppet/type/package/rpm.rb @@ -14,6 +14,9 @@ module Puppet output = %x{#{cmd} 2>/dev/null}.chomp if $? != 0 + #if Puppet[:debug] + # puts output + #end return nil end @@ -68,7 +71,7 @@ module Puppet # raise "installation not implemented yet" #} - def remove + def uninstall cmd = "rpm -e %s" % self.name output = %x{#{cmd}} if $? != 0 diff --git a/lib/puppet/type/package/sun.rb b/lib/puppet/type/package/sun.rb index b67bdaf5a..a9a8116d7 100755 --- a/lib/puppet/type/package/sun.rb +++ b/lib/puppet/type/package/sun.rb @@ -118,7 +118,7 @@ module Puppet # raise "installation not implemented yet" #} - def remove + def uninstall cmd = "pkgrm -n %s 2>&1" % self.name output = %x{#{cmd}} if $? != 0 diff --git a/lib/puppet/type/package/yum.rb b/lib/puppet/type/package/yum.rb index b7b833e9c..5a9361392 100755 --- a/lib/puppet/type/package/yum.rb +++ b/lib/puppet/type/package/yum.rb @@ -19,6 +19,7 @@ module Puppet # What's the latest package version available? def latest cmd = "yum list %s" % self.name + self.info "Executing %s" % cmd.inspect output = %x{#{cmd} 2>&1} unless $? == 0 @@ -38,6 +39,12 @@ module Puppet end def update + # Yum can't update packages that aren't there; we have to install + # them first + if self.is(:ensure) == :absent + self.info "performing initial install" + return self.install + end cmd = "yum -y update %s" % self.name self.info "Executing %s" % cmd.inspect diff --git a/lib/puppet/type/pfile.rb b/lib/puppet/type/pfile.rb index 6a52d31e9..2b553abd3 100644 --- a/lib/puppet/type/pfile.rb +++ b/lib/puppet/type/pfile.rb @@ -9,7 +9,15 @@ require 'puppet/server/fileserver' module Puppet newtype(:file) do @doc = "Manages local files, including setting ownership and - permissions, and allowing creation of both files and directories." + permissions, creation of both files and directories, and + retrieving entire files from remote servers. As Puppet matures, it + expected that the ``file`` element will be used less and less to + manage content, and instead native elements will be used to do so. + + If you find that you are often copying files in from a central + location, rather than using native elements, please contact + Reductive Labs and we can hopefully work with you to develop a + native element to support what you are doing." newparam(:path) do desc "The path to the file to manage. Must be fully qualified." @@ -18,7 +26,7 @@ module Puppet newparam(:backup) do desc "Whether files should be backed up before - being replaced. If a ``filebucket`` is specified, files will be + being replaced. If a filebucket_ is specified, files will be backed up there; else, they will be backed up in the same directory with a ``.puppet-bak`` extension." @@ -391,8 +399,8 @@ module Puppet sourceobj, path = uri2obj(source) # we'll set this manually as necessary - if @arghash.include?(:create) - @arghash.delete(:create) + if @arghash.include?(:ensure) + @arghash.delete(:ensure) end # okay, we've got our source object; now we need to @@ -453,7 +461,7 @@ module Puppet # want to overwrite whatever it did. This is a bit # of a hack, but oh well, source is definitely special. next if name == :source - state.is = :notfound + state.is = :absent } return end @@ -539,17 +547,17 @@ module Puppet class FileSource attr_accessor :mount, :root, :server, :local end -end -# We put all of the states in separate files, because there are so many -# of them. The order these are loaded is important, because it determines -# the order they are in the state list. -require 'puppet/type/pfile/create' -require 'puppet/type/pfile/checksum' -require 'puppet/type/pfile/content' -require 'puppet/type/pfile/source' -require 'puppet/type/pfile/uid' -require 'puppet/type/pfile/group' -require 'puppet/type/pfile/mode' -require 'puppet/type/pfile/type' + # We put all of the states in separate files, because there are so many + # of them. The order these are loaded is important, because it determines + # the order they are in the state list. + require 'puppet/type/pfile/ensure' + require 'puppet/type/pfile/checksum' + require 'puppet/type/pfile/content' + require 'puppet/type/pfile/source' + require 'puppet/type/pfile/uid' + require 'puppet/type/pfile/group' + require 'puppet/type/pfile/mode' + require 'puppet/type/pfile/type' +end # $Id$ diff --git a/lib/puppet/type/pfile/checksum.rb b/lib/puppet/type/pfile/checksum.rb index 813157d51..2e8d68d96 100755 --- a/lib/puppet/type/pfile/checksum.rb +++ b/lib/puppet/type/pfile/checksum.rb @@ -6,7 +6,7 @@ module Puppet Puppet.type(:file).newstate(:checksum) do desc "How to check whether a file has changed. **md5**/*lite-md5*/ *time*/*mtime*" - @event = :file_modified + @event = :file_changed @unmanaged = true @@ -96,7 +96,7 @@ module Puppet return :nosum end else - # We can't use :notfound here, because then it'll match on + # We can't use :absent here, because then it'll match on # non-existent files return :nosum end @@ -111,7 +111,7 @@ module Puppet end unless FileTest.exists?(@parent.name) - self.is = :notfound + self.is = :absent return end @@ -141,7 +141,7 @@ module Puppet @parent.name end - if @is == :notfound + if @is == :absent self.retrieve if self.insync? @@ -153,7 +153,7 @@ module Puppet # If we still can't retrieve a checksum, it means that # the file still doesn't exist - if @is == :notfound + if @is == :absent # if they're copying, then we won't worry about the file # not existing yet unless @parent.state(:source) @@ -168,7 +168,7 @@ module Puppet # If the sums are different, then return an event. if self.updatesum - return :file_modified + return :file_changed else return nil end @@ -188,7 +188,7 @@ module Puppet error = Puppet::Error.new("%s has invalid checksum" % @parent.name) raise error - #elsif @should == :notfound + #elsif @should == :absent # error = Puppet::Error.new("%s has invalid 'should' checksum" % # @parent.name) # raise error @@ -212,6 +212,7 @@ module Puppet result = false end state[@parent.name][@checktypes[0]] = @is + self.info "result is %s" % result.inspect return result end end diff --git a/lib/puppet/type/pfile/content.rb b/lib/puppet/type/pfile/content.rb index f11377275..9468f2140 100755 --- a/lib/puppet/type/pfile/content.rb +++ b/lib/puppet/type/pfile/content.rb @@ -3,7 +3,22 @@ module Puppet desc "Specify the contents of a file as a string. Newlines, tabs, and spaces can be specified using the escaped syntax (e.g., \\n for a newline). The primary purpose of this parameter is to provide a kind of limited - templating." + templating:: + + define resolve(nameserver1, nameserver2, domain, search) { + $str = \"search $search + domain $domain + nameserver $nameserver1 + nameserver $nameserver2 + \" + + file { \"/etc/resolv.conf\": + content => $str + } + } + + Yes, it's very primitive, and it's useless for larger files, but it + is mostly meant as a stopgap measure for simple cases." def change_to_s "synced" @@ -13,7 +28,7 @@ module Puppet # but I really don't feel like dealing with the complexity right now. def retrieve unless FileTest.exists?(@parent.name) - @is = :notfound + @is = :absent return end begin @@ -38,7 +53,7 @@ module Puppet [@parent.name, detail] end - if @is == :notfound + if @is == :absent return :file_created else return :file_changed diff --git a/lib/puppet/type/pfile/create.rb b/lib/puppet/type/pfile/ensure.rb index 4b7ee1e15..ab5639937 100755 --- a/lib/puppet/type/pfile/create.rb +++ b/lib/puppet/type/pfile/ensure.rb @@ -1,40 +1,108 @@ module Puppet - Puppet.type(:file).newstate(:create) do + Puppet.type(:file).ensurable do require 'etc' desc "Whether to create files that don't currently exist. - **false**/*true*/*file*/*directory*" - - @event = :file_created - - munge do |value| - # default to just about anything meaning 'true' - case value - when "false", false, nil: - false - when "true", true, "file", "plain", /^f/: - "file" - when "directory", /^d/: - "directory" - when :notfound: - # this is where a creation is being rolled back - :notfound - else - raise Puppet::Error, "Cannot create files of type %s" % value + Possible values are *absent*, *present* (equivalent to *file*), + **file**/*directory*. Specifying 'absent' will delete the file, + although currently this will not recursively delete directories. + + This is the only element with an *ensure* state that does not have + a default value." + + # Most 'ensure' states have a default, but with files we, um, don't. + nodefault + + #newvalue(:false) do + # # If they say "false" here, we just don't do anything at all; either + # # the file is there or it's not. + #end + + newvalue(:absent) do + File.unlink(@parent.name) + end + + aliasvalue(:false, :absent) + + newvalue(:file) do + mode = @parent.should(:mode) + Puppet::Util.asuser(asuser(), @parent.should(:group)) { + f = nil + if mode + f = File.open(@parent[:path],"w", mode) + else + f = File.open(@parent[:path],"w") + end + + if @parent[:content] + f.print @parent.should(:content) + end + f.flush + f.close + } + return :file_created + end + + aliasvalue(:present, :file) + + newvalue(:directory) do + mode = @parent.should(:mode) + Puppet::Util.asuser(asuser()) { + if mode + Dir.mkdir(@parent.name,mode) + else + Dir.mkdir(@parent.name) + end + } + return :directory_created + end + + def asuser + if @parent.should(:owner) and ! @parent.should(:owner).is_a?(Symbol) + writeable = Puppet::Util.asuser(@parent.should(:owner)) { + FileTest.writable?(File.dirname(@parent[:path])) + } + + # If the parent directory is writeable, then we execute + # as the user in question. Otherwise we'll rely on + # the 'owner' state to do things. + if writeable + asuser = @parent.should(:owner) + end + end + + return asuser + end + + def check + basedir = File.dirname(@parent.name) + + if ! FileTest.exists?(basedir) + raise Puppet::Error, + "Can not create %s; parent directory does not exist" % + @parent.name + elsif ! FileTest.directory?(basedir) + raise Puppet::Error, + "Can not create %s; %s is not a directory" % + [@parent.name, dirname] end end def retrieve if stat = @parent.stat(true) - @is = stat.ftype + @is = stat.ftype.intern else - @is = :notfound + if self.should == :false + @is = :false + else + @is = :absent + end end #self.debug "'exists' state is %s" % self.is end - def sync + def disabled_sync event = nil basedir = File.dirname(@parent.name) @@ -94,7 +162,7 @@ module Puppet end } event = :directory_created - when :notfound: + when :absent: # this is where the file should be deleted... # This value is only valid when we're rolling back a creation, diff --git a/lib/puppet/type/pfile/group.rb b/lib/puppet/type/pfile/group.rb index 5bb297fa2..c523f612e 100755 --- a/lib/puppet/type/pfile/group.rb +++ b/lib/puppet/type/pfile/group.rb @@ -4,7 +4,7 @@ module Puppet require 'etc' desc "Which group should own the file. Argument can be either group name or group ID." - @event = :inode_changed + @event = :file_changed def id2name(id) begin @@ -95,11 +95,11 @@ module Puppet # we'll just let it fail, but we should probably set things up so # that users get warned if they try to change to an unacceptable group. def sync - if @is == :notfound + if @is == :absent @parent.stat(true) self.retrieve - if @is == :notfound + if @is == :absent self.err "File '%s' does not exist; cannot chgrp" % @parent[:path] return nil @@ -118,7 +118,7 @@ module Puppet [@parent[:path], self.should, detail.message]) raise error end - return :inode_changed + return :file_changed end end end diff --git a/lib/puppet/type/pfile/mode.rb b/lib/puppet/type/pfile/mode.rb index 297e5cb1c..31d1a264a 100755 --- a/lib/puppet/type/pfile/mode.rb +++ b/lib/puppet/type/pfile/mode.rb @@ -6,7 +6,7 @@ module Puppet require 'etc' desc "Mode the file should be. Currently relatively limited: you must specify the exact mode the file should be." - @event = :inode_changed + @event = :file_changed # Our modes are octal, so make sure they print correctly. Other # valid values are symbols, basically @@ -83,18 +83,18 @@ module Puppet end end else - self.is = :notfound + self.is = :absent end #self.debug "chmod state is %o" % self.is end def sync - if @is == :notfound + if @is == :absent @parent.stat(true) self.retrieve #self.debug "%s: after refresh, is '%s'" % [self.class.name,@is] - if @is == :notfound + if @is == :absent self.info "File does not exist; cannot set mode" % @parent.name return nil @@ -108,7 +108,7 @@ module Puppet mode = self.should - if mode == :notfound + if mode == :absent # This is really only valid for create states... return nil end @@ -120,7 +120,7 @@ module Puppet [@parent.name, detail.message]) raise error end - return :inode_changed + return :file_changed end end end diff --git a/lib/puppet/type/pfile/source.rb b/lib/puppet/type/pfile/source.rb index b8f6e3045..d6a11dd7a 100755 --- a/lib/puppet/type/pfile/source.rb +++ b/lib/puppet/type/pfile/source.rb @@ -1,6 +1,5 @@ module Puppet - - # Copy files from a local or remote source. + # Copy files from a local or remote source. Puppet.type(:file).newstate(:source) do PINPARAMS = [:mode, :type, :owner, :group, :checksum] @@ -8,7 +7,26 @@ module Puppet desc "Copy a file over the current file. Uses `checksum` to determine when a file should be copied. Valid values are either fully qualified paths to files, or URIs. Currently supported URI - types are *puppet* and *file*." + types are *puppet* and *file*. + + This is one of the primary mechanisms for getting content into + applications that Puppet does not directly support and is very + useful for those configuration files that don't change much across + sytems. For instance:: + + class sendmail { + file { \"/etc/mail/sendmail.cf\": + source => \"puppet://server/module/sendmail.cf\" + } + } + + See the `fileserver docs`_ for information on how to configure + and use file services within Puppet. + + + .. _fileserver docs: /projects/puppet/documentation/fsconfigref + + " # Ask the file server to describe our file. def describe(source) @@ -98,41 +116,41 @@ module Puppet when "file": if sum = @parent.state(:checksum) if sum.is - if sum.is == :notfound + if sum.is == :absent sum.retrieve end @is = sum.is else - @is = :notfound + @is = :absent end else self.info "File does not have checksum" - @is = :notfound + @is = :absent end @should = [@stats[:checksum]] - if state = @parent.state(:create) - unless state.should == "file" - self.notice( - "File %s had both create and source enabled" % - @parent.name - ) - @parent.delete(:create) - end - end + #if state = @parent.state(:ensure) + # unless state.should == "file" + # self.notice( + # "File %s had both create and source enabled" % + # @parent.name + # ) + # @parent.delete(:ensure) + # end + #end # If we're a directory, then do not copy anything, and instead just # create the directory using the 'create' state. when "directory": - if state = @parent.state(:create) + if state = @parent.state(:ensure) unless state.should == "directory" state.should = "directory" end else - @parent[:create] = "directory" - @parent.state(:create).retrieve + @parent[:ensure] = "directory" + @parent.state(:ensure).retrieve end - # we'll let the :create state do our work + # we'll let the :ensure state do our work @should.clear @is = true # FIXME We should at least support symlinks, I would think... @@ -223,12 +241,13 @@ module Puppet # try to create it with the correct modes to start # we should also be changing our effective uid/gid, but... - if @parent.should(:mode) and @parent.should(:mode) != :notfound + if @parent.should(:mode) and @parent.should(:mode) != :absent args.push @parent.should(:mode) end # FIXME we should also change our effective user and group id + exists = File.exists?(@parent.name) begin File.open(*args) { |f| f.print contents @@ -256,7 +275,11 @@ module Puppet [@parent.name, detail] end - return :file_changed + if exists + return :file_changed + else + return :file_created + end end end end diff --git a/lib/puppet/type/pfile/type.rb b/lib/puppet/type/pfile/type.rb index 7d761c40b..0ea548c26 100755 --- a/lib/puppet/type/pfile/type.rb +++ b/lib/puppet/type/pfile/type.rb @@ -11,7 +11,7 @@ module Puppet if stat = @parent.stat(true) @is = stat.ftype else - @is = :notfound + @is = :absent end # so this state is never marked out of sync diff --git a/lib/puppet/type/pfile/uid.rb b/lib/puppet/type/pfile/uid.rb index 3f1add774..fc9129669 100755 --- a/lib/puppet/type/pfile/uid.rb +++ b/lib/puppet/type/pfile/uid.rb @@ -3,7 +3,7 @@ module Puppet require 'etc' desc "To whom the file should belong. Argument can be user name or user ID." - @event = :inode_changed + @event = :file_changed def id2name(id) if id.is_a?(Symbol) @@ -81,7 +81,7 @@ module Puppet def retrieve unless stat = @parent.stat(true) - @is = :notfound + @is = :absent return end @@ -92,7 +92,7 @@ module Puppet # it's an OS X bug, since it shows up in perl, too. if @is > 120000 self.warning "current state is silly: %s" % @is - @is = :notfound + @is = :absent end end @@ -135,10 +135,10 @@ module Puppet end end - if @is == :notfound + if @is == :absent @parent.stat(true) self.retrieve - if @is == :notfound + if @is == :absent self.info "File does not exist; cannot set owner" return nil end @@ -155,7 +155,7 @@ module Puppet [user, detail] end - return :inode_changed + return :file_changed end end end diff --git a/lib/puppet/type/pfilebucket.rb b/lib/puppet/type/pfilebucket.rb index d17f681af..dfe1bd4db 100755 --- a/lib/puppet/type/pfilebucket.rb +++ b/lib/puppet/type/pfilebucket.rb @@ -10,7 +10,13 @@ module Puppet for backing up. It stores files and returns the MD5 sum, which can later be used to retrieve the file if restoration becomes necessary. A filebucket does not do any work itself; instead, - it can be specified as the value of *backup* in a **file** object." + it can be specified as the value of *backup* in a **file** object. + + Currently, filebuckets are only useful for manual retrieval of + accidentally removed files (e.g., you look in the log for the md5 + sum and retrieve the file with that sum from the filebucket), but + when transactions are fully supported filebuckets will be used to + undo transactions." @states = [] diff --git a/lib/puppet/type/pprocess.rb b/lib/puppet/type/pprocess.rb deleted file mode 100644 index dad39cd2c..000000000 --- a/lib/puppet/type/pprocess.rb +++ /dev/null @@ -1,95 +0,0 @@ -# DISABLED -# I'm only working on services, not processes, right now - -module Puppet - class State - class PProcessRunning < State - @doc = "Whether a process should be running. **true**/*false*" - def retrieve - running = 0 - regex = Regexp.new(@params[:pattern]) - begin - # this ps is only tested on Solaris - # XXX yeah, this definitely needs to be fixed... - %x{ps -ef -U #{@params[:user]}}.split("\n").each { |process| - if regex.match(process) - running += 1 - end - } - rescue - # this isn't correct, but what the hell - Puppet::Message.new( - :level => :error, - :source => self.parent, - :message => "Failed to run ps" - ) - end - - self.state = running - debug "there are #{running} #{self.parent} processes for start" - end - - def <=>(other) - self.state < 1 - end - - def fix - require 'etc' - # ruby is really cool - uid = 0 - if @params[:user].is_a? Integer - uid = @params[:user] - else - uid = Etc.getpwnam(@params[:user]).uid - end - Kernel.fork { - PProcess.uid = uid - PProcess.euid = uid - string = @params[:binary] + (@params[:arguments] || "") - Puppet::Message.new( - :level => :notice, - :source => self.parent, - :message => "starting" - ) - Kernel.exec(string) - } - end - end - end - class Type - class PProcess < Type - attr_reader :stat, :path - @parameters = [:start, :stop, :user, :pattern, :binary, :arguments] - @name = :process - - @paramdoc[:start] = "How to start the process. Must be a fully - qualified path." - @paramdoc[:stop] = "How to stop the process. Must be a fully - qualified path." - @paramdoc[:user] = "Which user to run the proces as." - @paramdoc[:pattern] = "The search pattern to use to determine - whether the process is currently running." - @paramdoc[:binary] = "The binary to actually execute." - @paramdoc[:arguments] = "The arguments to pass the binary." - - @doc = "**Disabled. Use `service` instead.** Manage running - processes." - - @namevar = :pattern - - Puppet::Relation.new(self, Puppet::Operation::Start, { - :user => :user, - :pattern => :pattern, - :binary => :binary, - :arguments => :arguments - }) - - Puppet::Relation.new(self, Puppet::Operation::Stop, { - :user => :user, - :pattern => :pattern - }) - - end # Puppet.type(:pprocess) - end # Puppet::Type - -end diff --git a/lib/puppet/type/service.rb b/lib/puppet/type/service.rb index b526aae33..464da9b8d 100644 --- a/lib/puppet/type/service.rb +++ b/lib/puppet/type/service.rb @@ -7,12 +7,16 @@ module Puppet newtype(:service) do - @doc = "Manage running services. Rather than supporting managing - individual processes, puppet uses init scripts to simplify - specification of how to start, stop, or test processes. The - `path` parameter is provided to enable creation of multiple - init script directories, including supporting them for normal - users." + @doc = "Manage running services. Service support unfortunately varies + widely by platform -- some platforms have very little if any + concept of a running service, and some have a very codified and + powerful concept. Puppet's service support will generally be able + to make up for any inherent shortcomings (e.g., if there is no + 'status' command, then Puppet will look in the process table for a + command matching the service name), but the more information you + can provide the better behaviour you will get. Or, you can just + use a platform that has very good service support." + attr_reader :stat # newstate(:enabled) do @@ -101,7 +105,9 @@ module Puppet end newparam(:type) do - desc "The service type" + desc "The service type. For most platforms, it does not make + sense to change set this parameter, as the default is based on + the builtin service facilities." defaultto { @parent.class.defaulttype } @@ -119,23 +125,30 @@ module Puppet end newparam(:binary) do desc "The path to the daemon. This is only used for - systems that do not support init scripts." + systems that do not support init scripts. This binary will be + used to start the service if no ``start`` parameter is + provided." end newparam(:hasstatus) do desc "Declare the the service's init script has a - functional status command. This is assumed to be default for - most systems, although there might be platforms on which this is - assumed to be true." + functional status command. Based on testing, it was found + that a large number of init scripts on different platforms do + not support any kind of status command; thus, you must specify + manually whether the service you are running has such a + command (or you can specify a specific command using the + ``status`` parameter). + + If you do not specify anything, then the service name will be + looked for in the process table." end newparam(:name) do desc "The name of the service to run. This name - is used to find the init script in the search path." + is used to find the service in whatever service subsystem it + is in." isnamevar end newparam(:path) do - desc "The search path for finding init scripts. - There is currently no default, but hopefully soon there will - be a reasonable default for all platforms." + desc "The search path for finding init scripts." munge do |value| paths = [] @@ -168,25 +181,32 @@ module Puppet This is used for stopping services on platforms that do not support init scripts, and is also used for determining service status on those service whose init scripts do not include a status - command." + command. + + If this is left unspecified and is needed to check the status + of a service, then the service name will be used instead. + + The pattern can be a simple string or any legal Ruby pattern." defaultto { @parent.name } end newparam(:restart) do desc "Specify a *restart* command manually. If left - unspecified, the restart method will be determined automatically." + unspecified, the service will be stopped and then started." end newparam(:start) do - desc "Specify a *start* command manually. If left - unspecified, the start method will be determined automatically." + desc "Specify a *start* command manually. Most service subsystems + support a ``start`` command, so this will not need to be + specified." end newparam(:status) do desc "Specify a *status* command manually. If left - unspecified, the status method will be determined automatically." + unspecified, the status method will be determined + automatically, usually by looking for the service int he + process table." end newparam(:stop) do - desc "Specify a *stop* command manually. If left - unspecified, the stop method will be determined automatically." + desc "Specify a *stop* command manually." end # Create new subtypes of service management. diff --git a/lib/puppet/type/state.rb b/lib/puppet/type/state.rb index 6dff82765..bad42ec74 100644 --- a/lib/puppet/type/state.rb +++ b/lib/puppet/type/state.rb @@ -40,10 +40,39 @@ class State < Puppet::Parameter define_method("set_" + name.to_s, &block) end + def self.aliasvalue(name, other) + @statevalues ||= {} + unless @statevalues.include?(other) + raise Puppet::DevError, "Cannot alias nonexistent value %s" % other + end + + @aliasvalues ||= {} + @aliasvalues[name] = other + end + + def self.alias(name) + @aliasvalues[name] + end + + def self.defaultvalues + newvalue(:present) do + @parent.create + end + + newvalue(:absent) do + @parent.destroy + end + + # This doc will probably get overridden + @doc ||= "The basic state that the object should be in." + end + # Return the list of valid values. def self.values @statevalues ||= {} + @aliasvalues ||= {} + #[@aliasvalues.keys, @statevalues.keys].flatten @statevalues.keys end @@ -75,7 +104,6 @@ class State < Puppet::Parameter end if event and event.is_a?(Symbol) - self.log "got event back %s" % event return event else # Return the appropriate event. @@ -86,6 +114,9 @@ class State < Puppet::Parameter (@parent.class.name.to_s + "_changed").intern end + #self.log "made event %s because 'should' is %s, 'is' is %s" % + # [event, self.should.inspect, self.is.inspect] + return event end end @@ -232,6 +263,12 @@ class State < Puppet::Parameter # The default 'sync' method only selects among a list of registered # values. def sync + if self.insync? + self.info "already in sync" + return nil + else + self.info "%s vs %s" % [self.is.inspect, self.should.inspect] + end unless self.class.values raise Puppet::DevError, "No values defined for %s" % self.class.name @@ -241,6 +278,24 @@ class State < Puppet::Parameter self.set end + munge do |value| + if self.class.values.empty? + # This state isn't using defined values to do its work. + return value + end + intern = value.to_s.intern + # If it's a valid value, always return it as a symbol. + if self.class.values.include?(intern) + retval = intern + elsif other = self.class.alias(intern) + self.info "returning alias %s for %s" % [other, intern] + retval = other + else + retval = value + end + retval + end + # Verify that the passed value is valid. validate do |value| if self.class.values.empty? @@ -250,7 +305,7 @@ class State < Puppet::Parameter unless value.is_a?(Symbol) value = value.to_s.intern end - unless self.class.values.include?(value) + unless self.class.values.include?(value) or self.class.alias(value) raise Puppet::Error, "Invalid '%s' value '%s'. Valid values are '%s'" % [self.class.name, value, self.class.values.join(", ")] @@ -302,17 +357,24 @@ class State < Puppet::Parameter def self.inherited(sub) # Add in the two states that everyone will have. sub.class_eval do - newvalue(:present) do - @parent.create - end + end + end - newvalue(:absent) do - @parent.destroy + def change_to_s + begin + if @is == :absent + return "created" + elsif self.should == :absent + return "removed" + else + return "%s changed '%s' to '%s'" % + [self.name, self.is_to_s, self.should_to_s] end - - # This doc will probably get overridden - @doc = "The fundamental states that the object can be in. Allowed - values are %s." % self.values.join(", ") + rescue Puppet::Error, Puppet::DevError + raise + rescue => detail + raise Puppet::DevError, "Could not convert change %s to string: %s" % + [self.name, detail] end end diff --git a/lib/puppet/type/symlink.rb b/lib/puppet/type/symlink.rb index 2be33cb1d..37e60d6f6 100755 --- a/lib/puppet/type/symlink.rb +++ b/lib/puppet/type/symlink.rb @@ -91,7 +91,18 @@ module Puppet newparam(:recurse) do desc "If target is a directory, recursively create directories (using `file`'s `source` parameter) and link all - contained files." + contained files. For instance:: + + # The Solaris Blastwave repository installs everything + # in /opt/csw; link it into /usr/local + symlink { \"/usr/local\": + target => \"/opt/csw\", + recurse => 1 + } + + + Note that this does not link directories -- any directories + are created in the destination, and any files are linked over." munge do |value| @stat = nil diff --git a/lib/puppet/type/tidy.rb b/lib/puppet/type/tidy.rb index 61df0a80f..235d26e95 100755 --- a/lib/puppet/type/tidy.rb +++ b/lib/puppet/type/tidy.rb @@ -8,7 +8,8 @@ module Puppet @doc = "Remove unwanted files based on specific criteria." newparam(:path) do - desc "The path to the file to manage. Must be fully qualified." + desc "The path to the file or directory to manage. Must be fully + qualified." isnamevar end @@ -62,8 +63,8 @@ module Puppet end newparam(:type) do - desc "Set the mechanism for determining age. Access - time is the default mechanism, but modification." + desc "Set the mechanism for determining age. + **atime**/*mtime*/*ctime*." munge do |type| case type @@ -81,7 +82,8 @@ module Puppet end newparam(:rmdirs) do - desc "Tidy directories in addition to files." + desc "Tidy directories in addition to files; that is, remove + directories whose age is older than the specified criteria." end newstate(:tidyup) do diff --git a/lib/puppet/type/user.rb b/lib/puppet/type/user.rb index 3b342f785..317d86422 100755 --- a/lib/puppet/type/user.rb +++ b/lib/puppet/type/user.rb @@ -155,7 +155,15 @@ module Puppet cannot delete them. Theoretically all of the parameters are optional, but if no parameters are specified the comment will be set to the user name in order to make the internals work out - correctly." + correctly. + + This element type uses the prescribed native tools for creating + groups and generally uses POSIX APIs for retrieving information + about them. It does not directly modify /etc/passwd or anything. + + For most platforms, the tools used are ``useradd`` and its ilk; + for Mac OS X, NetInfo is used. This is currently unconfigurable, + but if you desperately need it to be so, please contact us." @netinfodir = "users" diff --git a/test/executables/puppetmodule.rb b/test/executables/puppetmodule.rb index c0020779d..56173c4b6 100755 --- a/test/executables/puppetmodule.rb +++ b/test/executables/puppetmodule.rb @@ -25,7 +25,7 @@ class TestPuppetModule < Test::Unit::TestCase createdfile = tempfile() File.open(file, "w") { |f| - f.puts "class yaytest { file { \"#{createdfile}\": create => true } }" + f.puts "class yaytest { file { \"#{createdfile}\": ensure => file } }" } output = nil diff --git a/test/language/interpreter.rb b/test/language/interpreter.rb index 9dbf8dc99..a9d448a67 100755 --- a/test/language/interpreter.rb +++ b/test/language/interpreter.rb @@ -22,7 +22,7 @@ class TestInterpreter < Test::Unit::TestCase createdfile = tempfile() File.open(file, "w") { |f| - f.puts "node %s { file { \"%s\": create => true, mode => 755 } }\n" % + f.puts "node %s { file { \"%s\": ensure => file, mode => 755 } }\n" % [node, createdfile] } diff --git a/test/other/events.rb b/test/other/events.rb index f57fd3272..be319724c 100755 --- a/test/other/events.rb +++ b/test/other/events.rb @@ -21,7 +21,7 @@ class TestEvents < Test::Unit::TestCase name = tempfile() file = Puppet.type(:file).create( :name => name, - :create => true + :ensure => "file" ) exec = Puppet.type(:exec).create( :name => "echo true", @@ -41,7 +41,7 @@ class TestEvents < Test::Unit::TestCase name = tempfile() file = Puppet.type(:file).create( :name => name, - :create => true + :ensure => "file" ) exec = Puppet.type(:exec).create( :name => "echo true", @@ -76,7 +76,7 @@ class TestEvents < Test::Unit::TestCase name = tempfile() + l.to_s objects[l] = Puppet.type(:file).create( :name => name, - :create => true + :ensure => "file" ) @@tmpfiles << name when :b diff --git a/test/other/log.rb b/test/other/log.rb index 0bc2656ea..16f458193 100644 --- a/test/other/log.rb +++ b/test/other/log.rb @@ -182,7 +182,7 @@ class TestLog < Test::Unit::TestCase path = tempfile() file = Puppet.type(:file).create( :path => path, - :create => true + :ensure => "file" ) assert_nothing_raised { diff --git a/test/other/storage.rb b/test/other/storage.rb index 0a52196d6..64f08cdc7 100755 --- a/test/other/storage.rb +++ b/test/other/storage.rb @@ -62,6 +62,16 @@ class TestParsedFile < Test::Unit::TestCase } threads.each { |th| th.join } end + + def test_emptyrestore + Puppet::Storage.load + Puppet::Storage.store + Puppet::Storage.clear + Puppet::Storage.load + state = Puppet::Storage.state('newstate') + assert_same Hash, state.class + assert_equal 0, state.size + end end # $Id$ diff --git a/test/other/transactions.rb b/test/other/transactions.rb index 5a00fbe09..ed6843104 100644 --- a/test/other/transactions.rb +++ b/test/other/transactions.rb @@ -123,9 +123,9 @@ class TestTransactions < Test::Unit::TestCase file[:mode] = "755" } - trans = assert_events([:inode_changed, :inode_changed], component) + trans = assert_events([:file_changed, :file_changed], component) - assert_rollback_events(trans, [:inode_changed, :inode_changed], "file") + assert_rollback_events(trans, [:file_changed, :file_changed], "file") assert_nothing_raised() { file.retrieve @@ -188,7 +188,7 @@ class TestTransactions < Test::Unit::TestCase file[:mode] = "755" } - trans = assert_events( [:inode_changed], component) + trans = assert_events( [:file_changed], component) assert(FileTest.exists?(execfile), "Execfile does not exist") File.unlink(execfile) @@ -196,7 +196,7 @@ class TestTransactions < Test::Unit::TestCase file[:group] = @groups[1] } - trans = assert_events([:inode_changed], component) + trans = assert_events([:file_changed], component) assert(FileTest.exists?(execfile), "Execfile does not exist") end @@ -227,7 +227,7 @@ class TestTransactions < Test::Unit::TestCase file[:mode] = "755" } - trans = assert_events([:inode_changed, :inode_changed], component) + trans = assert_events([:file_changed, :file_changed], component) end diff --git a/test/parser/parser.rb b/test/parser/parser.rb index 4752ce35e..68209a0d2 100644 --- a/test/parser/parser.rb +++ b/test/parser/parser.rb @@ -66,7 +66,7 @@ class TestParser < Test::Unit::TestCase @@tmpfiles << name File.open(file, "w") { |f| - f.puts "file { \"%s\": create => true, mode => 755 }\n" % + f.puts "file { \"%s\": ensure => file, mode => 755 }\n" % name } end diff --git a/test/puppettest.rb b/test/puppettest.rb index fd966f930..34d48ff52 100644 --- a/test/puppettest.rb +++ b/test/puppettest.rb @@ -289,7 +289,7 @@ module ServerTest @createdfile = File.join(tmpdir(), self.class.to_s + "servermanifesttesting") File.open(file, "w") { |f| - f.puts "file { \"%s\": create => true, mode => 755 }\n" % @createdfile + f.puts "file { \"%s\": ensure => file, mode => 755 }\n" % @createdfile } @@tmpfiles << @createdfile diff --git a/test/server/master.rb b/test/server/master.rb index 3ccd176f8..a300a18a4 100644 --- a/test/server/master.rb +++ b/test/server/master.rb @@ -134,7 +134,7 @@ class TestMaster < Test::Unit::TestCase Puppet::Type.allclear File.open(manifest, "w") { |f| - f.puts "file { \"%s\": create => true }\n" % file2 + f.puts "file { \"%s\": ensure => file }\n" % file2 } assert_nothing_raised { client.getconfig diff --git a/test/types/basic.rb b/test/types/basic.rb index edc6bc66d..082a8342f 100644 --- a/test/types/basic.rb +++ b/test/types/basic.rb @@ -33,7 +33,7 @@ class TestBasic < Test::Unit::TestCase @@tmpfiles << @filepath @configfile = Puppet.type(:file).create( :path => @filepath, - :create => true, + :ensure => "file", :checksum => "md5" ) } diff --git a/test/types/exec.rb b/test/types/exec.rb index 370fe380f..7ecf8a26d 100755 --- a/test/types/exec.rb +++ b/test/types/exec.rb @@ -171,7 +171,7 @@ class TestExec < Test::Unit::TestCase # verify that only the file_changed event was kicked off, not the # command_executed assert_equal( - [:file_modified], + [:file_changed], events ) end @@ -213,7 +213,7 @@ class TestExec < Test::Unit::TestCase comp = newcomp("Testing", file, exec) - assert_events([:file_changed, :executed_command], comp) + assert_events([:file_created, :executed_command], comp) end # Verify that we auto-require any managed scripts. diff --git a/test/types/file.rb b/test/types/file.rb index 65d1560cd..b9e85839e 100644 --- a/test/types/file.rb +++ b/test/types/file.rb @@ -124,7 +124,7 @@ class TestFile < Test::Unit::TestCase file = Puppet.type(:file).create( :path => path, :owner => user.name, - :create => true, + :ensure => "file", :mode => "755" ) } @@ -221,7 +221,7 @@ class TestFile < Test::Unit::TestCase assert_nothing_raised() { file = Puppet.type(:file).create( :name => path, - :create => true + :ensure => "file" ) } assert_events([:file_created], file) @@ -240,7 +240,7 @@ class TestFile < Test::Unit::TestCase assert_nothing_raised() { file = Puppet.type(:file).create( :name => path, - :create => "directory" + :ensure => "directory" ) } assert(! FileTest.directory?(path), "Directory %s already exists" % @@ -261,7 +261,7 @@ class TestFile < Test::Unit::TestCase assert_nothing_raised() { file[:mode] = mode } - assert_events([:inode_changed], file) + assert_events([:file_changed], file) assert_events([], file) assert(file.insync?()) @@ -283,15 +283,13 @@ class TestFile < Test::Unit::TestCase # try it both with files that exist and ones that don't files = [exists, nonexists] initstorage - File.open(exists,"w") { |of| - 10.times { - of.puts rand(100) - } + File.open(exists,File::CREAT|File::TRUNC|File::WRONLY) { |of| + of.puts "initial text" } types.each { |type| files.each { |path| if Puppet[:debug] - Puppet.info "Testing %s on %s" % [type,path] + Puppet.warning "Testing %s on %s" % [type,path] end file = nil events = nil @@ -299,12 +297,12 @@ class TestFile < Test::Unit::TestCase assert_nothing_raised() { file = Puppet.type(:file).create( :name => path, - :create => true, + :ensure => "file", :checksum => type ) } comp = Puppet.type(:component).create( - :name => "componentfile" + :name => "checksum %s" % type ) comp.push file trans = nil @@ -324,16 +322,19 @@ class TestFile < Test::Unit::TestCase # we don't want to kick off an event the first time we # come across a file assert( - ! events.include?(:file_modified) + ! events.include?(:file_changed) ) assert_nothing_raised() { - File.open(path,"w") { |of| - of.puts rand(100) + File.open(path,File::CREAT|File::TRUNC|File::WRONLY) { |of| + of.puts "some more text, yo" } } Puppet.type(:file).clear Puppet.type(:component).clear - sleep 1 + + # We have to sleep because the time resolution of the time-based + # mechanisms is greater than one second + sleep 1.1 # now recreate the file assert_nothing_raised() { @@ -343,17 +344,41 @@ class TestFile < Test::Unit::TestCase ) } comp = Puppet.type(:component).create( - :name => "componentfile" + :name => "checksum, take 2, %s" % type ) comp.push file trans = nil - assert_events([:file_modified], comp) + + # If the file was missing, it should not generate an event + # when it gets created. + if path =~ /nonexists/e + assert_events([], comp) + else + assert_events([:file_changed], comp) + end + assert_nothing_raised() { + File.unlink(path) + File.open(path,File::CREAT|File::TRUNC|File::WRONLY) { |of| + # We have to put a certain amount of text in here or + # the md5-lite test fails + 2.times { + of.puts rand(100) + } + of.flush + } + } + #assert_apply(comp) + assert_events([:file_changed], comp) # verify that we're actually getting notified when a file changes assert_nothing_raised() { Puppet.type(:file).clear Puppet.type(:component).clear } + + if path =~ /nonexists/ + File.unlink(path) + end } } end @@ -444,7 +469,7 @@ class TestFile < Test::Unit::TestCase file = mkfile( :name => path, :recurse => true, - :create => true + :ensure => "file" ) } @@ -483,7 +508,7 @@ class TestFile < Test::Unit::TestCase assert_nothing_raised { file = Puppet.type(:file).create( :name => tempfile(), - :create => true + :ensure => "file" ) } @@ -577,12 +602,12 @@ class TestFile < Test::Unit::TestCase baseobj = Puppet.type(:file).create( :name => basedir, - :create => "directory" + :ensure => "directory" ) subobj = Puppet.type(:file).create( :name => subfile, - :create => "file" + :ensure => "file" ) Puppet::Type.finalize @@ -640,7 +665,7 @@ class TestFile < Test::Unit::TestCase assert_nothing_raised { file = Puppet.type(:file).create( :name => subpath, - :create => "directory", + :ensure => "directory", :recurse => true ) } diff --git a/test/types/filesources.rb b/test/types/filesources.rb index 5ae728c81..ba401b446 100755 --- a/test/types/filesources.rb +++ b/test/types/filesources.rb @@ -565,7 +565,7 @@ class TestFileSources < Test::Unit::TestCase } comp = newcomp(file) - assert_events([:file_changed], comp) + assert_events([:file_created], comp) assert(File.exists?(to), "File does not exist") diff --git a/test/types/package.rb b/test/types/package.rb index 1723f973d..36da3c0cd 100644 --- a/test/types/package.rb +++ b/test/types/package.rb @@ -167,6 +167,7 @@ class TestPackages < Test::Unit::TestCase comp = newcomp("package", pkg) + Puppet.err :mark assert_events([:package_created], comp, "package") # then uninstall it @@ -177,6 +178,8 @@ class TestPackages < Test::Unit::TestCase pkg.retrieve + p pkg + assert(! pkg.insync?, "Package is in sync") assert_events([:package_removed], comp, "package") diff --git a/test/types/type.rb b/test/types/type.rb index 5426ec669..7d087b30b 100644 --- a/test/types/type.rb +++ b/test/types/type.rb @@ -59,7 +59,7 @@ class TestType < Test::Unit::TestCase system("rm -f %s" % path) file = Puppet.type(:file).create( :path => path, - :create => true, + :ensure => "file", :recurse => true, :checksum => "md5" ) @@ -75,7 +75,7 @@ class TestType < Test::Unit::TestCase system("rm -f %s" % path) file = Puppet.type(:file).create( "path" => path, - "create" => true, + "ensure" => "file", "recurse" => true, "checksum" => "md5" ) @@ -144,7 +144,7 @@ class TestType < Test::Unit::TestCase assert_nothing_raised { baseobj = Puppet.type(:file).create( :name => file, - :create => true, + :ensure => "file", :alias => ["funtest"] ) } |