puppet 2.6.2 → 2.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. data/CHANGELOG +61 -0
  2. data/ext/envpuppet +80 -0
  3. data/ext/puppet-load.rb +62 -26
  4. data/ext/puppetstoredconfigclean.rb +0 -2
  5. data/lib/puppet.rb +1 -1
  6. data/lib/puppet/daemon.rb +2 -2
  7. data/lib/puppet/defaults.rb +10 -8
  8. data/lib/puppet/external/pson/pure/generator.rb +5 -12
  9. data/lib/puppet/indirector/catalog/compiler.rb +8 -4
  10. data/lib/puppet/network/handler/fileserver.rb +2 -0
  11. data/lib/puppet/network/server.rb +2 -2
  12. data/lib/puppet/node/environment.rb +4 -0
  13. data/lib/puppet/parser/ast/collection.rb +34 -51
  14. data/lib/puppet/parser/ast/leaf.rb +10 -2
  15. data/lib/puppet/parser/ast/resource.rb +4 -3
  16. data/lib/puppet/parser/compiler.rb +2 -2
  17. data/lib/puppet/parser/functions.rb +4 -2
  18. data/lib/puppet/parser/lexer.rb +2 -1
  19. data/lib/puppet/parser/parser_support.rb +3 -3
  20. data/lib/puppet/provider.rb +2 -2
  21. data/lib/puppet/provider/confine/exists.rb +1 -4
  22. data/lib/puppet/provider/mount.rb +1 -1
  23. data/lib/puppet/provider/nameservice.rb +3 -1
  24. data/lib/puppet/provider/package/openbsd.rb +6 -10
  25. data/lib/puppet/provider/service/freebsd.rb +4 -1
  26. data/lib/puppet/provider/service/launchd.rb +1 -1
  27. data/lib/puppet/provider/user/user_role_add.rb +8 -6
  28. data/lib/puppet/provider/user/useradd.rb +7 -8
  29. data/lib/puppet/rails.rb +2 -6
  30. data/lib/puppet/rails/host.rb +0 -72
  31. data/lib/puppet/resource.rb +22 -0
  32. data/lib/puppet/resource/type.rb +18 -13
  33. data/lib/puppet/type/exec.rb +1 -7
  34. data/lib/puppet/type/schedule.rb +5 -5
  35. data/lib/puppet/util.rb +20 -18
  36. data/lib/puppet/util/command_line.rb +1 -1
  37. data/lib/puppet/util/file_locking.rb +6 -3
  38. data/lib/puppet/util/metric.rb +1 -1
  39. data/lib/puppet/util/rdoc.rb +5 -4
  40. data/lib/puppet/util/rdoc/generators/puppet_generator.rb +6 -0
  41. data/lib/puppet/util/reference.rb +1 -10
  42. data/lib/puppet/util/suidmanager.rb +1 -1
  43. data/lib/puppet/util/zaml.rb +4 -1
  44. data/spec/integration/indirector/bucket_file/rest_spec.rb +10 -2
  45. data/spec/integration/indirector/certificate_revocation_list/rest_spec.rb +10 -2
  46. data/spec/integration/parser/functions_spec.rb +21 -0
  47. data/spec/integration/parser/ruby_manifest_spec.rb +1 -1
  48. data/spec/integration/ssl/certificate_authority_spec.rb +1 -3
  49. data/spec/integration/util/file_locking_spec.rb +31 -11
  50. data/spec/spec_helper.rb +1 -1
  51. data/spec/unit/application/apply_spec.rb +1 -1
  52. data/spec/unit/daemon_spec.rb +3 -9
  53. data/spec/unit/indirector/catalog/compiler_spec.rb +9 -8
  54. data/spec/unit/network/handler/fileserver_spec.rb +2 -4
  55. data/spec/unit/network/server_spec.rb +3 -10
  56. data/spec/unit/parser/ast/collection_spec.rb +4 -0
  57. data/spec/unit/parser/ast/leaf_spec.rb +43 -1
  58. data/spec/unit/parser/ast/resource_spec.rb +133 -88
  59. data/spec/unit/parser/compiler_spec.rb +8 -8
  60. data/spec/unit/parser/lexer_spec.rb +1 -0
  61. data/spec/unit/parser/parser_spec.rb +9 -2
  62. data/spec/unit/provider/confine/exists_spec.rb +6 -13
  63. data/spec/unit/provider/mount_spec.rb +8 -1
  64. data/spec/unit/provider/service/freebsd_spec.rb +50 -0
  65. data/spec/unit/provider/ssh_authorized_key/parsed_spec.rb +1 -2
  66. data/spec/unit/provider/user/user_role_add_spec.rb +1 -1
  67. data/spec/unit/provider/user/useradd_spec.rb +42 -0
  68. data/spec/unit/rails_spec.rb +82 -22
  69. data/spec/unit/resource/type_spec.rb +13 -13
  70. data/spec/unit/type/schedule_spec.rb +21 -49
  71. data/spec/unit/util/command_line_spec.rb +2 -2
  72. data/spec/unit/util/file_locking_spec.rb +28 -24
  73. data/spec/unit/util/{json_spec.rb → pson_spec.rb} +17 -0
  74. data/spec/unit/util/rdoc_spec.rb +9 -1
  75. data/spec/unit/util/storage_spec.rb +2 -3
  76. data/test/other/provider.rb +1 -12
  77. data/test/other/report.rb +2 -5
  78. data/test/puppet/tc_suidmanager.rb +5 -14
  79. data/test/ral/manager/type.rb +1 -1
  80. data/test/ral/providers/provider.rb +3 -3
  81. data/test/util/metrics.rb +2 -2
  82. metadata +8 -6
  83. data/spec/integration/indirector/rest_spec.rb +0 -525
@@ -88,7 +88,7 @@ module Puppet::Util::SUIDManager
88
88
  module_function :initgroups
89
89
 
90
90
  def run_and_capture(command, new_uid=nil, new_gid=nil)
91
- output = Puppet::Util.execute(command, :failonfail => false, :uid => new_uid, :gid => new_gid)
91
+ output = Puppet::Util.execute(command, :failonfail => false, :combine => true, :uid => new_uid, :gid => new_gid)
92
92
  [output, $CHILD_STATUS.dup]
93
93
  end
94
94
  module_function :run_and_capture
@@ -120,6 +120,9 @@ class Object
120
120
  def to_yaml_properties
121
121
  instance_variables.sort # Default YAML behavior
122
122
  end
123
+ def yaml_property_munge(x)
124
+ x
125
+ end
123
126
  def zamlized_class_name(root)
124
127
  cls = self.class
125
128
  "!ruby/#{root.name.downcase}#{cls == root ? '' : ":#{cls.respond_to?(:name) ? cls.name : cls}"}"
@@ -136,7 +139,7 @@ class Object
136
139
  z.nl
137
140
  v[1..-1].to_zaml(z) # Remove leading '@'
138
141
  z.emit(': ')
139
- instance_variable_get(v).to_zaml(z)
142
+ yaml_property_munge(instance_variable_get(v)).to_zaml(z)
140
143
  }
141
144
  end
142
145
  }
@@ -36,8 +36,16 @@ describe "Filebucket REST Terminus" do
36
36
  @host = Puppet::SSL::Host.new(Puppet[:certname])
37
37
 
38
38
  @params = { :port => 34343, :handlers => [ :file_bucket_file ] }
39
- @server = Puppet::Network::Server.new(@params)
40
- @server.listen
39
+ retries = 0
40
+ begin
41
+ @server = Puppet::Network::Server.new(@params)
42
+ @server.listen
43
+ rescue Errno::EADDRINUSE => e
44
+ sleep 0.1
45
+ puts "Port 34343 is in use; waiting for it to be free" if retries == 50
46
+ retry if (retries += 1) < 100
47
+ pending "Can't run too many simultaneous tests"
48
+ end
41
49
 
42
50
  @old_terminus = Puppet::FileBucket::File.indirection.terminus_class
43
51
  Puppet::FileBucket::File.terminus_class = :rest
@@ -33,8 +33,16 @@ describe "Certificate REST Terminus" do
33
33
  ca.generate(Puppet[:certname]) unless Puppet::SSL::Certificate.find(Puppet[:certname])
34
34
 
35
35
  @params = { :port => 34343, :handlers => [ :certificate_revocation_list ] }
36
- @server = Puppet::Network::Server.new(@params)
37
- @server.listen
36
+ retries = 0
37
+ begin
38
+ @server = Puppet::Network::Server.new(@params)
39
+ @server.listen
40
+ rescue Errno::EADDRINUSE => e
41
+ sleep 0.1
42
+ puts "Port 34343 is in use; waiting for it to be free" if retries == 50
43
+ retry if (retries += 1) < 100
44
+ pending "Can't run too many simultaneous tests"
45
+ end
38
46
 
39
47
  # And make sure we've generated the CRL
40
48
  @crl = ca.crl
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.dirname(__FILE__) + '/../../spec_helper'
4
+
5
+ describe Puppet::Parser::Functions do
6
+ before :each do
7
+ Puppet::Parser::Functions.rmfunction("template") if Puppet::Parser::Functions.function("template")
8
+ end
9
+
10
+ it "should support multiple threads autoloading the same function" do
11
+ threads = []
12
+ lambda {
13
+ 10.times { |a|
14
+ threads << Thread.new {
15
+ Puppet::Parser::Functions.function("template")
16
+ }
17
+ }
18
+ }.should_not raise_error
19
+ threads.each { |t| t.join }
20
+ end
21
+ end
@@ -69,7 +69,7 @@ describe "Pure ruby manifests" do
69
69
  write_file('foo.rb', "hostclass 'bar' do file 'test_file', :owner => 'root', :mode => '644' end")
70
70
  catalog = compile("import 'foo'\ninclude bar")
71
71
  file = catalog.resource("File[test_file]")
72
- file.should be_a Puppet::Resource
72
+ file.should be_a(Puppet::Resource)
73
73
  file.type.should == 'File'
74
74
  file.title.should == 'test_file'
75
75
  file.exported.should_not be
@@ -121,9 +121,7 @@ describe Puppet::SSL::CertificateAuthority do
121
121
  it "should save valid certificates" do
122
122
  @ca.sign("luke.madstop.com")
123
123
 
124
- ssl = %x{which openssl}
125
-
126
- unless ssl
124
+ unless ssl = Puppet::Util::which('openssl')
127
125
  pending "No ssl available"
128
126
  else
129
127
  ca_cert = Puppet[:cacert]
@@ -5,28 +5,30 @@ Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f
5
5
  require 'puppet/util/file_locking'
6
6
 
7
7
  describe Puppet::Util::FileLocking do
8
- it "should be able to keep file corruption from happening when there are multiple writers" do
9
- file = Tempfile.new("puppetspec")
10
- filepath = file.path
11
- file.close!()
12
- file = filepath
13
- data = {:a => :b, :c => "A string", :d => "another string", :e => %w{an array of strings}}
14
- File.open(file, "w") { |f| f.puts YAML.dump(data) }
8
+ before :each do
9
+ @file = Tempfile.new("puppetspec")
10
+ filepath = @file.path
11
+ @file.close!()
12
+ @file = filepath
13
+ @data = {:a => :b, :c => "A string", :d => "another string", :e => %w{an array of strings}}
14
+ File.open(@file, "w") { |f| f.puts YAML.dump(@data) }
15
+ end
15
16
 
17
+ it "should be able to keep file corruption from happening when there are multiple writers threads" do
16
18
  threads = []
17
19
  sync = Sync.new
18
20
  9.times { |a|
19
21
  threads << Thread.new {
20
22
  9.times { |b|
21
23
  sync.synchronize(Sync::SH) {
22
- Puppet::Util::FileLocking.readlock(file) { |f|
23
- YAML.load(f.read).should == data
24
+ Puppet::Util::FileLocking.readlock(@file) { |f|
25
+ YAML.load(f.read).should == @data
24
26
  }
25
27
  }
26
28
  sleep 0.01
27
29
  sync.synchronize(Sync::EX) {
28
- Puppet::Util::FileLocking.writelock(file) { |f|
29
- f.puts YAML.dump(data)
30
+ Puppet::Util::FileLocking.writelock(@file) { |f|
31
+ f.puts YAML.dump(@data)
30
32
  }
31
33
  }
32
34
  }
@@ -34,4 +36,22 @@ describe Puppet::Util::FileLocking do
34
36
  }
35
37
  threads.each { |th| th.join }
36
38
  end
39
+
40
+ it "should be able to keep file corruption from happening when there are multiple writers processes" do
41
+ unless Process.fork
42
+ 50.times { |b|
43
+ Puppet::Util::FileLocking.writelock(@file) { |f|
44
+ f.puts YAML.dump(@data)
45
+ }
46
+ sleep 0.01
47
+ }
48
+ Kernel.exit!
49
+ end
50
+
51
+ 50.times { |c|
52
+ Puppet::Util::FileLocking.readlock(@file) { |f|
53
+ YAML.load(f.read).should == @data
54
+ }
55
+ }
56
+ end
37
57
  end
@@ -20,7 +20,7 @@ module PuppetSpec
20
20
  FIXTURE_DIR = File.join(dir = File.expand_path(File.dirname(__FILE__)), "fixtures") unless defined?(FIXTURE_DIR)
21
21
  end
22
22
 
23
- require 'spec/lib/puppet_spec/files'
23
+ require 'lib/puppet_spec/files'
24
24
  require 'monkey_patches/alias_should_to_must'
25
25
  require 'monkey_patches/add_confine_and_runnable_to_rspec_dsl'
26
26
  require 'monkey_patches/publicize_methods'
@@ -312,7 +312,7 @@ describe Puppet::Application::Apply do
312
312
  end
313
313
 
314
314
  it "should apply the catalog" do
315
- @catalog.expects(:apply).returns(stub_everything 'transaction')
315
+ @catalog.expects(:apply).returns(stub_everything('transaction'))
316
316
 
317
317
  @apply.main
318
318
  end
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby"
1
+ #!/usr/bin/env ruby
2
2
 
3
3
  require File.dirname(__FILE__) + '/../spec_helper'
4
4
  require 'puppet/daemon'
@@ -142,11 +142,7 @@ describe Puppet::Daemon do
142
142
  describe "when creating its pidfile" do
143
143
  it "should use an exclusive mutex" do
144
144
  Puppet.settings.expects(:value).with(:name).returns "me"
145
-
146
- sync = mock 'sync'
147
- Puppet::Util.expects(:sync).with("me").returns sync
148
-
149
- sync.expects(:synchronize).with(Sync::EX)
145
+ Puppet::Util.expects(:synchronize_on).with("me",Sync::EX)
150
146
  @daemon.create_pidfile
151
147
  end
152
148
 
@@ -180,10 +176,8 @@ describe Puppet::Daemon do
180
176
  it "should use an exclusive mutex" do
181
177
  Puppet.settings.expects(:value).with(:name).returns "me"
182
178
 
183
- sync = mock 'sync'
184
- Puppet::Util.expects(:sync).with("me").returns sync
179
+ Puppet::Util.expects(:synchronize_on).with("me",Sync::EX)
185
180
 
186
- sync.expects(:synchronize).with(Sync::EX)
187
181
  @daemon.remove_pidfile
188
182
  end
189
183
 
@@ -6,6 +6,7 @@
6
6
  require File.dirname(__FILE__) + '/../../../spec_helper'
7
7
 
8
8
  require 'puppet/indirector/catalog/compiler'
9
+ require 'puppet/rails'
9
10
 
10
11
  describe Puppet::Resource::Catalog::Compiler do
11
12
  before do
@@ -33,8 +34,8 @@ describe Puppet::Resource::Catalog::Compiler do
33
34
  Puppet::Node.stubs(:find).with('node1').returns(node1)
34
35
  Puppet::Node.stubs(:find).with('node2').returns(node2)
35
36
 
36
- compiler.find(stub('request', :node => 'node1', :options => {}))
37
- compiler.find(stub('node2request', :node => 'node2', :options => {}))
37
+ compiler.find(stub('request', :key => 'node1', :node => 'node1', :options => {}))
38
+ compiler.find(stub('node2request', :key => 'node2', :node => 'node2', :options => {}))
38
39
  end
39
40
 
40
41
  it "should provide a method for determining if the catalog is networked" do
@@ -70,7 +71,7 @@ describe Puppet::Resource::Catalog::Compiler do
70
71
  @node = Puppet::Node.new @name
71
72
  @node.stubs(:merge)
72
73
  Puppet::Node.stubs(:find).returns @node
73
- @request = stub 'request', :key => "does not matter", :node => @name, :options => {}
74
+ @request = stub 'request', :key => @name, :node => @name, :options => {}
74
75
  end
75
76
 
76
77
  it "should directly use provided nodes" do
@@ -80,14 +81,14 @@ describe Puppet::Resource::Catalog::Compiler do
80
81
  @compiler.find(@request)
81
82
  end
82
83
 
83
- it "should use the request's node name if no explicit node is provided" do
84
+ it "should use the authenticated node name if no request key is provided" do
85
+ @request.stubs(:key).returns(nil)
84
86
  Puppet::Node.expects(:find).with(@name).returns(@node)
85
87
  @compiler.expects(:compile).with(@node)
86
88
  @compiler.find(@request)
87
89
  end
88
90
 
89
- it "should use the provided node name if no explicit node is provided and no authenticated node information is available" do
90
- @request.expects(:node).returns nil
91
+ it "should use the provided node name by default" do
91
92
  @request.expects(:key).returns "my_node"
92
93
 
93
94
  Puppet::Node.expects(:find).with("my_node").returns @node
@@ -198,7 +199,7 @@ describe Puppet::Resource::Catalog::Compiler do
198
199
  @compiler = Puppet::Resource::Catalog::Compiler.new
199
200
  @name = "me"
200
201
  @node = mock 'node'
201
- @request = stub 'request', :node => @name, :options => {}
202
+ @request = stub 'request', :key => @name, :options => {}
202
203
  @compiler.stubs(:compile)
203
204
  end
204
205
 
@@ -217,7 +218,7 @@ describe Puppet::Resource::Catalog::Compiler do
217
218
  @compiler = Puppet::Resource::Catalog::Compiler.new
218
219
  @name = "me"
219
220
  @node = mock 'node'
220
- @request = stub 'request', :node => @name, :options => {}
221
+ @request = stub 'request', :key => @name, :options => {}
221
222
  @compiler.stubs(:compile)
222
223
  Puppet::Node.stubs(:find).with(@name).returns(@node)
223
224
  end
@@ -4,9 +4,8 @@ require File.dirname(__FILE__) + '/../../../spec_helper'
4
4
 
5
5
  require 'puppet/network/handler/fileserver'
6
6
 
7
-
8
7
  describe Puppet::Network::Handler::FileServer do
9
- require 'tmpdir'
8
+ include PuppetSpec::Files
10
9
 
11
10
  def create_file(filename)
12
11
  File.open(filename, "w") { |f| f.puts filename}
@@ -20,8 +19,7 @@ describe Puppet::Network::Handler::FileServer do
20
19
  end
21
20
 
22
21
  before do
23
- @basedir = File.join(Dir.tmpdir, "test_network_handler")
24
- Dir.mkdir(@basedir)
22
+ @basedir = tmpdir("test_network_handler")
25
23
  @file = File.join(@basedir, "aFile")
26
24
  @link = File.join(@basedir, "aLink")
27
25
  create_file(@file)
@@ -5,6 +5,7 @@
5
5
 
6
6
  require File.dirname(__FILE__) + '/../../spec_helper'
7
7
  require 'puppet/network/server'
8
+ require 'puppet/network/handler'
8
9
 
9
10
  describe Puppet::Network::Server do
10
11
  before do
@@ -161,11 +162,7 @@ describe Puppet::Network::Server do
161
162
  describe "when creating its pidfile" do
162
163
  it "should use an exclusive mutex" do
163
164
  Puppet.settings.expects(:value).with(:name).returns "me"
164
-
165
- sync = mock 'sync'
166
- Puppet::Util.expects(:sync).with("me").returns sync
167
-
168
- sync.expects(:synchronize).with(Sync::EX)
165
+ Puppet::Util.expects(:synchronize_on).with("me",Sync::EX)
169
166
  @server.create_pidfile
170
167
  end
171
168
 
@@ -198,11 +195,7 @@ describe Puppet::Network::Server do
198
195
  describe "when removing its pidfile" do
199
196
  it "should use an exclusive mutex" do
200
197
  Puppet.settings.expects(:value).with(:name).returns "me"
201
-
202
- sync = mock 'sync'
203
- Puppet::Util.expects(:sync).with("me").returns sync
204
-
205
- sync.expects(:synchronize).with(Sync::EX)
198
+ Puppet::Util.expects(:synchronize_on).with("me",Sync::EX)
206
199
  @server.remove_pidfile
207
200
  end
208
201
 
@@ -5,6 +5,8 @@ require File.dirname(__FILE__) + '/../../../spec_helper'
5
5
  describe Puppet::Parser::AST::Collection do
6
6
  before :each do
7
7
  @scope = stub_everything 'scope'
8
+ @mytype = stub_everything('mytype')
9
+ @scope.stubs(:find_resource_type).returns @mytype
8
10
  @compiler = stub_everything 'compile'
9
11
  @scope.stubs(:compiler).returns(@compiler)
10
12
 
@@ -24,6 +26,8 @@ describe Puppet::Parser::AST::Collection do
24
26
 
25
27
  it "should instantiate a Collector for this type" do
26
28
  collection = Puppet::Parser::AST::Collection.new :form => :virtual, :type => "test"
29
+ @test_type = stub 'type', :name => 'test'
30
+ @scope.expects(:find_resource_type).with('test').returns @test_type
27
31
 
28
32
  Puppet::Parser::Collector.expects(:new).with(@scope, "test", nil, nil, :virtual)
29
33
 
@@ -49,7 +49,7 @@ describe Puppet::Parser::AST::String do
49
49
  end
50
50
  it "should return a dup of its value" do
51
51
  value = ""
52
- Puppet::Parser::AST::String.new( :value => value ).evaluate(stub 'scope').should_not be_equal(value)
52
+ Puppet::Parser::AST::String.new( :value => value ).evaluate(stub('scope')).should_not be_equal(value)
53
53
  end
54
54
  end
55
55
  end
@@ -136,6 +136,22 @@ describe Puppet::Parser::AST::HashOrArrayAccess do
136
136
  access.evaluate(@scope).should == "val2"
137
137
  end
138
138
 
139
+ it "should be able to return an array member when index is a stringified number" do
140
+ @scope.stubs(:lookupvar).with("a").returns(["val1", "val2", "val3"])
141
+
142
+ access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "1" )
143
+
144
+ access.evaluate(@scope).should == "val2"
145
+ end
146
+
147
+ it "should raise an error when accessing an array with a key" do
148
+ @scope.stubs(:lookupvar).with("a").returns(["val1", "val2", "val3"])
149
+
150
+ access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "get_me_the_second_element_please" )
151
+
152
+ lambda { access.evaluate(@scope) }.should raise_error
153
+ end
154
+
139
155
  it "should be able to return an hash value" do
140
156
  @scope.stubs(:lookupvar).with("a").returns({ "key1" => "val1", "key2" => "val2", "key3" => "val3" })
141
157
 
@@ -144,6 +160,14 @@ describe Puppet::Parser::AST::HashOrArrayAccess do
144
160
  access.evaluate(@scope).should == "val2"
145
161
  end
146
162
 
163
+ it "should be able to return an hash value with a numerical key" do
164
+ @scope.stubs(:lookupvar).with("a").returns({ "key1" => "val1", "key2" => "val2", "45" => "45", "key3" => "val3" })
165
+
166
+ access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "45" )
167
+
168
+ access.evaluate(@scope).should == "45"
169
+ end
170
+
147
171
  it "should raise an error if the variable lookup didn't return an hash or an array" do
148
172
  @scope.stubs(:lookupvar).with("a").returns("I'm a string")
149
173
 
@@ -195,6 +219,24 @@ describe Puppet::Parser::AST::HashOrArrayAccess do
195
219
  scope.lookupvar("a").should be_include("b")
196
220
  end
197
221
 
222
+ it "should raise an error when assigning an array element with a key" do
223
+ @scope.stubs(:lookupvar).with("a").returns([])
224
+
225
+ access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "get_me_the_second_element_please" )
226
+
227
+ lambda { access.assign(@scope, "test") }.should raise_error
228
+ end
229
+
230
+ it "should be able to return an array member when index is a stringified number" do
231
+ scope = Puppet::Parser::Scope.new
232
+ scope.setvar("a", [])
233
+
234
+ access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "0" )
235
+
236
+ access.assign(scope, "val2")
237
+ scope.lookupvar("a").should == ["val2"]
238
+ end
239
+
198
240
  it "should raise an error when trying to overwrite an hash value" do
199
241
  @scope.stubs(:lookupvar).with("a").returns({ "key" => [ "a" , "b" ]})
200
242
  access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "key")
@@ -5,123 +5,168 @@ require File.dirname(__FILE__) + '/../../../spec_helper'
5
5
  describe Puppet::Parser::AST::Resource do
6
6
  ast = Puppet::Parser::AST
7
7
 
8
- before :each do
9
- @title = Puppet::Parser::AST::String.new(:value => "mytitle")
10
- @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))
11
- @scope = Puppet::Parser::Scope.new(:compiler => @compiler)
12
- @scope.stubs(:resource).returns(stub_everything)
13
- @resource = ast::Resource.new(:title => @title, :type => "file", :parameters => ast::ASTArray.new(:children => []) )
14
- @resource.stubs(:qualified_type).returns("Resource")
15
- end
16
-
17
- it "should evaluate all its parameters" do
18
- param = stub 'param'
19
- param.expects(:safeevaluate).with(@scope).returns Puppet::Parser::Resource::Param.new(:name => "myparam", :value => "myvalue", :source => stub("source"))
20
- @resource.stubs(:parameters).returns [param]
21
-
22
- @resource.evaluate(@scope)
23
- end
24
-
25
- it "should evaluate its title" do
26
- @resource.evaluate(@scope)[0].title.should == "mytitle"
27
- end
28
-
29
- it "should flatten the titles array" do
30
- titles = []
31
- %w{one two}.each do |title|
32
- titles << Puppet::Parser::AST::String.new(:value => title)
8
+ describe "for builtin types" do
9
+ before :each do
10
+ @title = Puppet::Parser::AST::String.new(:value => "mytitle")
11
+ @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))
12
+ @scope = Puppet::Parser::Scope.new(:compiler => @compiler)
13
+ @scope.stubs(:resource).returns(stub_everything)
14
+ @resource = ast::Resource.new(:title => @title, :type => "file", :parameters => ast::ASTArray.new(:children => []) )
15
+ @resource.stubs(:qualified_type).returns("Resource")
33
16
  end
34
17
 
35
- array = Puppet::Parser::AST::ASTArray.new(:children => titles)
18
+ it "should evaluate all its parameters" do
19
+ param = stub 'param'
20
+ param.expects(:safeevaluate).with(@scope).returns Puppet::Parser::Resource::Param.new(:name => "myparam", :value => "myvalue", :source => stub("source"))
21
+ @resource.stubs(:parameters).returns [param]
36
22
 
37
- @resource.title = array
38
- result = @resource.evaluate(@scope).collect { |r| r.title }
39
- result.should be_include("one")
40
- result.should be_include("two")
41
- end
23
+ @resource.evaluate(@scope)
24
+ end
42
25
 
43
- it "should create and return one resource objects per title" do
44
- titles = []
45
- %w{one two}.each do |title|
46
- titles << Puppet::Parser::AST::String.new(:value => title)
26
+ it "should evaluate its title" do
27
+ @resource.evaluate(@scope)[0].title.should == "mytitle"
47
28
  end
48
29
 
49
- array = Puppet::Parser::AST::ASTArray.new(:children => titles)
30
+ it "should flatten the titles array" do
31
+ titles = []
32
+ %w{one two}.each do |title|
33
+ titles << Puppet::Parser::AST::String.new(:value => title)
34
+ end
50
35
 
51
- @resource.title = array
52
- result = @resource.evaluate(@scope).collect { |r| r.title }
53
- result.should be_include("one")
54
- result.should be_include("two")
55
- end
36
+ array = Puppet::Parser::AST::ASTArray.new(:children => titles)
56
37
 
57
- it "should handover resources to the compiler" do
58
- titles = []
59
- %w{one two}.each do |title|
60
- titles << Puppet::Parser::AST::String.new(:value => title)
38
+ @resource.title = array
39
+ result = @resource.evaluate(@scope).collect { |r| r.title }
40
+ result.should be_include("one")
41
+ result.should be_include("two")
61
42
  end
62
43
 
63
- array = Puppet::Parser::AST::ASTArray.new(:children => titles)
44
+ it "should create and return one resource objects per title" do
45
+ titles = []
46
+ %w{one two}.each do |title|
47
+ titles << Puppet::Parser::AST::String.new(:value => title)
48
+ end
64
49
 
65
- @resource.title = array
66
- result = @resource.evaluate(@scope)
50
+ array = Puppet::Parser::AST::ASTArray.new(:children => titles)
67
51
 
68
- result.each do |res|
69
- @compiler.catalog.resource(res.ref).should be_instance_of(Puppet::Parser::Resource)
52
+ @resource.title = array
53
+ result = @resource.evaluate(@scope).collect { |r| r.title }
54
+ result.should be_include("one")
55
+ result.should be_include("two")
70
56
  end
71
- end
72
- it "should generate virtual resources if it is virtual" do
73
- @resource.virtual = true
74
57
 
75
- result = @resource.evaluate(@scope)
76
- result[0].should be_virtual
77
- end
58
+ it "should handover resources to the compiler" do
59
+ titles = []
60
+ %w{one two}.each do |title|
61
+ titles << Puppet::Parser::AST::String.new(:value => title)
62
+ end
78
63
 
79
- it "should generate virtual and exported resources if it is exported" do
80
- @resource.exported = true
64
+ array = Puppet::Parser::AST::ASTArray.new(:children => titles)
81
65
 
82
- result = @resource.evaluate(@scope)
83
- result[0].should be_virtual
84
- result[0].should be_exported
85
- end
66
+ @resource.title = array
67
+ result = @resource.evaluate(@scope)
86
68
 
87
- # Related to #806, make sure resources always look up the full path to the resource.
88
- describe "when generating qualified resources" do
89
- before do
90
- @scope = Puppet::Parser::Scope.new :compiler => Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))
91
- @parser = Puppet::Parser::Parser.new(Puppet::Node::Environment.new)
92
- @parser.newdefine "one"
93
- @parser.newdefine "one::two"
94
- @parser.newdefine "three"
95
- @twoscope = @scope.newscope(:namespace => "one")
96
- @twoscope.resource = @scope.resource
69
+ result.each do |res|
70
+ @compiler.catalog.resource(res.ref).should be_instance_of(Puppet::Parser::Resource)
71
+ end
97
72
  end
98
73
 
99
- def resource(type, params = nil)
100
- params ||= Puppet::Parser::AST::ASTArray.new(:children => [])
101
- Puppet::Parser::AST::Resource.new(:type => type, :title => Puppet::Parser::AST::String.new(:value => "myresource"), :parameters => params)
74
+ it "should generate virtual resources if it is virtual" do
75
+ @resource.virtual = true
76
+
77
+ result = @resource.evaluate(@scope)
78
+ result[0].should be_virtual
102
79
  end
103
80
 
104
- it "should be able to generate resources with fully qualified type information" do
105
- resource("two").evaluate(@twoscope)[0].type.should == "One::Two"
81
+ it "should generate virtual and exported resources if it is exported" do
82
+ @resource.exported = true
83
+
84
+ result = @resource.evaluate(@scope)
85
+ result[0].should be_virtual
86
+ result[0].should be_exported
106
87
  end
107
88
 
108
- it "should be able to generate resources with unqualified type information" do
109
- resource("one").evaluate(@twoscope)[0].type.should == "One"
89
+ # Related to #806, make sure resources always look up the full path to the resource.
90
+ describe "when generating qualified resources" do
91
+ before do
92
+ @scope = Puppet::Parser::Scope.new :compiler => Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))
93
+ @parser = Puppet::Parser::Parser.new(Puppet::Node::Environment.new)
94
+ @parser.newdefine "one"
95
+ @parser.newdefine "one::two"
96
+ @parser.newdefine "three"
97
+ @twoscope = @scope.newscope(:namespace => "one")
98
+ @twoscope.resource = @scope.resource
99
+ end
100
+
101
+ def resource(type, params = nil)
102
+ params ||= Puppet::Parser::AST::ASTArray.new(:children => [])
103
+ Puppet::Parser::AST::Resource.new(:type => type, :title => Puppet::Parser::AST::String.new(:value => "myresource"), :parameters => params)
104
+ end
105
+
106
+ it "should be able to generate resources with fully qualified type information" do
107
+ resource("two").evaluate(@twoscope)[0].type.should == "One::Two"
108
+ end
109
+
110
+ it "should be able to generate resources with unqualified type information" do
111
+ resource("one").evaluate(@twoscope)[0].type.should == "One"
112
+ end
113
+
114
+ it "should correctly generate resources that can look up builtin types" do
115
+ resource("file").evaluate(@twoscope)[0].type.should == "File"
116
+ end
117
+
118
+ it "should correctly generate resources that can look up defined classes by title" do
119
+ @scope.known_resource_types.add_hostclass Puppet::Resource::Type.new(:hostclass, "Myresource", {})
120
+ @scope.compiler.stubs(:evaluate_classes)
121
+ res = resource("class").evaluate(@twoscope)[0]
122
+ res.type.should == "Class"
123
+ res.title.should == "Myresource"
124
+ end
125
+
126
+ it "should evaluate parameterized classes when they are instantiated" do
127
+ @scope.known_resource_types.add_hostclass Puppet::Resource::Type.new(:hostclass, "Myresource", {})
128
+ @scope.compiler.expects(:evaluate_classes).with(['myresource'],@twoscope,false)
129
+ resource("class").evaluate(@twoscope)[0]
130
+ end
131
+
132
+ it "should fail for resource types that do not exist" do
133
+ lambda { resource("nosuchtype").evaluate(@twoscope) }.should raise_error(Puppet::ParseError)
134
+ end
110
135
  end
136
+ end
111
137
 
112
- it "should correctly generate resources that can look up builtin types" do
113
- resource("file").evaluate(@twoscope)[0].type.should == "File"
138
+ describe "for class resources" do
139
+ before do
140
+ @title = Puppet::Parser::AST::String.new(:value => "classname")
141
+ @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))
142
+ @scope = Puppet::Parser::Scope.new(:compiler => @compiler)
143
+ @scope.stubs(:resource).returns(stub_everything)
144
+ @resource = ast::Resource.new(:title => @title, :type => "Class", :parameters => ast::ASTArray.new(:children => []) )
145
+ @resource.stubs(:qualified_type).returns("Resource")
146
+ @type = Puppet::Resource::Type.new(:hostclass, "classname")
147
+ @compiler.known_resource_types.add(@type)
114
148
  end
115
149
 
116
- it "should correctly generate resources that can look up defined classes by title" do
117
- @scope.known_resource_types.add_hostclass Puppet::Resource::Type.new(:hostclass, "Myresource", {})
118
- res = resource("class").evaluate(@twoscope)[0]
119
- res.type.should == "Class"
120
- res.title.should == "Myresource"
150
+ it "should instantiate the class" do
151
+ @compiler.stubs(:evaluate_classes)
152
+ result = @resource.evaluate(@scope)
153
+ result.length.should == 1
154
+ result.first.ref.should == "Class[Classname]"
155
+ @compiler.catalog.resource("Class[Classname]").should equal(result.first)
121
156
  end
122
157
 
123
- it "should fail for resource types that do not exist" do
124
- lambda { resource("nosuchtype").evaluate(@twoscope) }.should raise_error(Puppet::ParseError)
158
+ it "should cause its parent to be evaluated" do
159
+ parent_type = Puppet::Resource::Type.new(:hostclass, "parentname")
160
+ @compiler.stubs(:evaluate_classes)
161
+ @compiler.known_resource_types.add(parent_type)
162
+ @type.parent = "parentname"
163
+ result = @resource.evaluate(@scope)
164
+ result.length.should == 1
165
+ result.first.ref.should == "Class[Classname]"
166
+ @compiler.catalog.resource("Class[Classname]").should equal(result.first)
167
+ @compiler.catalog.resource("Class[Parentname]").should be_instance_of(Puppet::Parser::Resource)
125
168
  end
169
+
126
170
  end
171
+
127
172
  end