puppet 3.1.0 → 3.1.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (42) hide show
  1. data/conf/auth.conf +3 -3
  2. data/lib/puppet/indirector/catalog/compiler.rb +13 -2
  3. data/lib/puppet/indirector/certificate_status/file.rb +5 -0
  4. data/lib/puppet/indirector/errors.rb +5 -0
  5. data/lib/puppet/indirector/file_bucket_file/file.rb +4 -0
  6. data/lib/puppet/indirector/file_bucket_file/selector.rb +4 -0
  7. data/lib/puppet/indirector/indirection.rb +2 -1
  8. data/lib/puppet/indirector/resource/active_record.rb +2 -0
  9. data/lib/puppet/indirector/resource/ral.rb +3 -0
  10. data/lib/puppet/indirector/resource/store_configs.rb +3 -0
  11. data/lib/puppet/indirector/resource/validator.rb +8 -0
  12. data/lib/puppet/indirector/rest.rb +4 -0
  13. data/lib/puppet/indirector/run/local.rb +4 -0
  14. data/lib/puppet/indirector/terminus.rb +20 -0
  15. data/lib/puppet/network/authconfig.rb +1 -1
  16. data/lib/puppet/network/formats.rb +3 -3
  17. data/lib/puppet/network/http/handler.rb +7 -2
  18. data/lib/puppet/network/http/rack/rest.rb +7 -2
  19. data/lib/puppet/network/http/webrick.rb +1 -0
  20. data/lib/puppet/parser/templatewrapper.rb +16 -16
  21. data/lib/puppet/util/monkey_patches.rb +38 -0
  22. data/lib/puppet/version.rb +1 -1
  23. data/spec/integration/file_serving/terminus_helper_spec.rb +1 -1
  24. data/spec/integration/indirector/catalog/queue_spec.rb +1 -1
  25. data/spec/integration/resource/catalog_spec.rb +1 -0
  26. data/spec/unit/indirector/catalog/compiler_spec.rb +29 -2
  27. data/spec/unit/indirector/indirection_spec.rb +17 -1
  28. data/spec/unit/indirector/terminus_spec.rb +45 -0
  29. data/spec/unit/network/authconfig_spec.rb +12 -0
  30. data/spec/unit/network/authorization_spec.rb +4 -0
  31. data/spec/unit/network/formats_spec.rb +6 -6
  32. data/spec/unit/network/http/connection_spec.rb +0 -1
  33. data/spec/unit/network/http/handler_spec.rb +25 -0
  34. data/spec/unit/network/http/rack/rest_spec.rb +17 -0
  35. data/spec/unit/network/http/webrick_spec.rb +4 -0
  36. data/spec/unit/parser/functions/inline_template_spec.rb +15 -44
  37. data/spec/unit/parser/functions/template_spec.rb +43 -56
  38. data/spec/unit/parser/templatewrapper_spec.rb +68 -91
  39. data/spec/unit/ssl/certificate_request_spec.rb +2 -0
  40. data/spec/unit/ssl/host_spec.rb +1 -0
  41. data/spec/unit/util/monkey_patches_spec.rb +20 -0
  42. metadata +2190 -2188
@@ -13,7 +13,7 @@ end
13
13
  describe Puppet::FileServing::TerminusHelper do
14
14
  it "should be able to recurse on a single file" do
15
15
  @path = Tempfile.new("fileset_integration")
16
- request = Puppet::Indirector::Request.new(:metadata, :find, @path.path, :recurse => true)
16
+ request = Puppet::Indirector::Request.new(:metadata, :find, @path.path, nil, :recurse => true)
17
17
 
18
18
  tester = TerminusHelperIntegrationTester.new
19
19
  lambda { tester.path2instances(request, @path.path) }.should_not raise_error
@@ -6,7 +6,7 @@ require 'puppet/resource/catalog'
6
6
  describe "Puppet::Resource::Catalog::Queue" do
7
7
  before do
8
8
  Puppet::Resource::Catalog.indirection.terminus(:queue)
9
- @catalog = Puppet::Resource::Catalog.new
9
+ @catalog = Puppet::Resource::Catalog.new("foo")
10
10
 
11
11
  @one = Puppet::Resource.new(:file, "/one")
12
12
  @two = Puppet::Resource.new(:file, "/two")
@@ -46,6 +46,7 @@ describe Puppet::Resource::Catalog do
46
46
  Puppet::Resource::Catalog.indirection.stubs(:terminus).returns terminus
47
47
 
48
48
  node = mock 'node'
49
+ terminus.stubs(:validate)
49
50
  terminus.expects(:find).with { |request| request.options[:use_node] == node }
50
51
  Puppet::Resource::Catalog.indirection.find("me", :use_node => node)
51
52
  end
@@ -53,13 +53,22 @@ describe Puppet::Resource::Catalog::Compiler do
53
53
  @request = Puppet::Indirector::Request.new(:catalog, :find, @name, nil, :node => @name)
54
54
  end
55
55
 
56
- it "should directly use provided nodes" do
56
+ it "should directly use provided nodes for a local request" do
57
57
  Puppet::Node.indirection.expects(:find).never
58
58
  @compiler.expects(:compile).with(@node)
59
59
  @request.stubs(:options).returns(:use_node => @node)
60
+ @request.stubs(:remote?).returns(false)
60
61
  @compiler.find(@request)
61
62
  end
62
63
 
64
+ it "rejects a provided node if the request is remote" do
65
+ @request.stubs(:options).returns(:use_node => @node)
66
+ @request.stubs(:remote?).returns(true)
67
+ expect {
68
+ @compiler.find(@request)
69
+ }.to raise_error Puppet::Error, /invalid option use_node/i
70
+ end
71
+
63
72
  it "should use the authenticated node name if no request key is provided" do
64
73
  @request.stubs(:key).returns(nil)
65
74
  Puppet::Node.indirection.expects(:find).with(@name, anything).returns(@node)
@@ -99,6 +108,24 @@ describe Puppet::Resource::Catalog::Compiler do
99
108
  @compiler.find(@request)
100
109
  end
101
110
 
111
+ it "requires `facts_format` option if facts are passed in" do
112
+ facts = Puppet::Node::Facts.new("mynode", :afact => "avalue")
113
+ request = Puppet::Indirector::Request.new(:catalog, :find, "mynode", nil, :facts => facts)
114
+ expect {
115
+ @compiler.find(request)
116
+ }.to raise_error ArgumentError, /no fact format provided for mynode/
117
+ end
118
+
119
+ it "rejects facts in the request from a different node" do
120
+ facts = Puppet::Node::Facts.new("differentnode", :afact => "avalue")
121
+ request = Puppet::Indirector::Request.new(
122
+ :catalog, :find, "mynode", nil, :facts => facts, :facts_format => "unused"
123
+ )
124
+ expect {
125
+ @compiler.find(request)
126
+ }.to raise_error Puppet::Error, /fact definition for the wrong node/i
127
+ end
128
+
102
129
  it "should return the results of compiling as the catalog" do
103
130
  Puppet::Node.indirection.stubs(:find).returns(@node)
104
131
  config = mock 'config'
@@ -133,7 +160,7 @@ describe Puppet::Resource::Catalog::Compiler do
133
160
  before do
134
161
  Facter.stubs(:value).returns "something"
135
162
  @compiler = Puppet::Resource::Catalog::Compiler.new
136
- @request = stub 'request', :options => {}
163
+ @request = Puppet::Indirector::Request.new(:catalog, :find, "hostname", nil)
137
164
 
138
165
  @facts = Puppet::Node::Facts.new('hostname', "fact" => "value", "architecture" => "i386")
139
166
  Puppet::Node::Facts.indirection.stubs(:save).returns(nil)
@@ -40,7 +40,7 @@ shared_examples_for "Indirection Delegator" do
40
40
  end
41
41
  end
42
42
 
43
- request = stub 'request', :key => "me", :options => {}
43
+ request = Puppet::Indirector::Request.new(:indirection, :find, "me", nil)
44
44
 
45
45
  @indirection.stubs(:request).returns request
46
46
 
@@ -101,6 +101,16 @@ shared_examples_for "Delegation Authorizer" do
101
101
  end
102
102
  end
103
103
 
104
+ shared_examples_for "Request validator" do
105
+ it "asks the terminus to validate the request" do
106
+ @terminus.expects(:validate).raises(Puppet::Indirector::ValidationError, "Invalid")
107
+ @terminus.expects(@method).never
108
+ expect {
109
+ @indirection.send(@method, "key")
110
+ }.to raise_error Puppet::Indirector::ValidationError
111
+ end
112
+ end
113
+
104
114
  describe Puppet::Indirector::Indirection do
105
115
  describe "when initializing" do
106
116
  # (LAK) I've no idea how to test this, really.
@@ -141,6 +151,7 @@ describe Puppet::Indirector::Indirection do
141
151
  before :each do
142
152
  @terminus_class = mock 'terminus_class'
143
153
  @terminus = mock 'terminus'
154
+ @terminus.stubs(:validate)
144
155
  @terminus_class.stubs(:new).returns(@terminus)
145
156
  @cache = stub 'cache', :name => "mycache"
146
157
  @cache_class = mock 'cache_class'
@@ -211,6 +222,7 @@ describe Puppet::Indirector::Indirection do
211
222
 
212
223
  it_should_behave_like "Indirection Delegator"
213
224
  it_should_behave_like "Delegation Authorizer"
225
+ it_should_behave_like "Request validator"
214
226
 
215
227
  it "should return the results of the delegation" do
216
228
  @terminus.expects(:find).returns(@instance)
@@ -384,6 +396,7 @@ describe Puppet::Indirector::Indirection do
384
396
 
385
397
  it_should_behave_like "Indirection Delegator"
386
398
  it_should_behave_like "Delegation Authorizer"
399
+ it_should_behave_like "Request validator"
387
400
 
388
401
  it "should return true if the head method returned true" do
389
402
  @terminus.expects(:head).returns(true)
@@ -501,6 +514,7 @@ describe Puppet::Indirector::Indirection do
501
514
 
502
515
  it_should_behave_like "Indirection Delegator"
503
516
  it_should_behave_like "Delegation Authorizer"
517
+ it_should_behave_like "Request validator"
504
518
 
505
519
  it "should return the result of removing the instance" do
506
520
  @terminus.stubs(:destroy).returns "yayness"
@@ -539,6 +553,7 @@ describe Puppet::Indirector::Indirection do
539
553
 
540
554
  it_should_behave_like "Indirection Delegator"
541
555
  it_should_behave_like "Delegation Authorizer"
556
+ it_should_behave_like "Request validator"
542
557
 
543
558
  it "should set the expiration date on any instances without one set" do
544
559
  @terminus.stubs(:search).returns([@instance])
@@ -707,6 +722,7 @@ describe Puppet::Indirector::Indirection do
707
722
  before do
708
723
  @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
709
724
  @terminus = mock 'terminus'
725
+ @terminus.stubs(:validate)
710
726
  @terminus_class = stub 'terminus class', :new => @terminus
711
727
  end
712
728
 
@@ -9,6 +9,10 @@ describe Puppet::Indirector::Terminus do
9
9
  class Puppet::AbstractConcept
10
10
  extend Puppet::Indirector
11
11
  indirects :abstract_concept
12
+ attr_accessor :name
13
+ def initialize(name = "name")
14
+ @name = name
15
+ end
12
16
  end
13
17
 
14
18
  class Puppet::AbstractConcept::Freedom < Puppet::Indirector::Code
@@ -23,6 +27,7 @@ describe Puppet::Indirector::Terminus do
23
27
  let :terminus_class do Puppet::AbstractConcept::Freedom end
24
28
  let :terminus do terminus_class.new end
25
29
  let :indirection do Puppet::AbstractConcept.indirection end
30
+ let :model do Puppet::AbstractConcept end
26
31
 
27
32
  it "should provide a method for setting terminus class documentation" do
28
33
  terminus_class.should respond_to(:desc)
@@ -216,4 +221,44 @@ describe Puppet::Indirector::Terminus do
216
221
  Puppet::Indirector::Terminus.terminus_classes('my_stuff').should == [:baz, :marathon]
217
222
  end
218
223
  end
224
+
225
+ describe "when validating a request" do
226
+ let :request do
227
+ Puppet::Indirector::Request.new(indirection.name, :find, "the_key", instance)
228
+ end
229
+
230
+ describe "`instance.name` does not match the key in the request" do
231
+ let(:instance) { model.new("wrong_key") }
232
+
233
+ it "raises an error " do
234
+ expect {
235
+ terminus.validate(request)
236
+ }.to raise_error(
237
+ Puppet::Indirector::ValidationError,
238
+ /Instance name .* does not match requested key/
239
+ )
240
+ end
241
+ end
242
+
243
+ describe "`instance` is not an instance of the model class" do
244
+ let(:instance) { mock "instance" }
245
+
246
+ it "raises an error" do
247
+ expect {
248
+ terminus.validate(request)
249
+ }.to raise_error(
250
+ Puppet::Indirector::ValidationError,
251
+ /Invalid instance type/
252
+ )
253
+ end
254
+ end
255
+
256
+ describe "the instance key and class match the request key and model class" do
257
+ let(:instance) { model.new("the_key") }
258
+
259
+ it "passes" do
260
+ terminus.validate(request)
261
+ end
262
+ end
263
+ end
219
264
  end
@@ -78,6 +78,18 @@ describe Puppet::Network::AuthConfig do
78
78
  @authconfig.rights['/'].should be_empty
79
79
  @authconfig.rights['/'].authentication.should be_false
80
80
  end
81
+
82
+ it '(CVE-2013-2275) allows report submission only for the node matching the certname by default' do
83
+ acl = {
84
+ :acl => "~ ^\/report\/([^\/]+)$",
85
+ :method => :save,
86
+ :allow => '$1',
87
+ :authenticated => true
88
+ }
89
+ @authconfig.stubs(:mk_acl)
90
+ @authconfig.expects(:mk_acl).with(acl)
91
+ @authconfig.insert_default_acl
92
+ end
81
93
  end
82
94
 
83
95
  describe "when checking authorization" do
@@ -11,6 +11,10 @@ describe Puppet::Network::Authorization do
11
11
 
12
12
  describe "when creating an authconfig object" do
13
13
  it "creates default ACL entries if no file has been read" do
14
+ # Other tests may have created an authconfig, so we have to undo that.
15
+ Puppet::Network::AuthConfigLoader.instance_variable_set(:@auth_config, nil)
16
+ Puppet::Network::AuthConfigLoader.instance_variable_set(:@auth_config_file, nil)
17
+
14
18
  Puppet::Network::AuthConfigParser.expects(:new_from_file).raises Errno::ENOENT
15
19
  Puppet::Network::AuthConfig.any_instance.expects(:insert_default_acl)
16
20
 
@@ -55,15 +55,15 @@ describe "Puppet Network Format" do
55
55
  @yaml.render_multiple(instances).should == "foo"
56
56
  end
57
57
 
58
- it "should intern by calling 'YAML.load'" do
58
+ it "should safely load YAML when interning" do
59
59
  text = "foo"
60
- YAML.expects(:load).with("foo").returns "bar"
60
+ YAML.expects(:safely_load).with("foo").returns "bar"
61
61
  @yaml.intern(String, text).should == "bar"
62
62
  end
63
63
 
64
- it "should intern multiples by calling 'YAML.load'" do
64
+ it "should safely load YAML when interning multiples" do
65
65
  text = "foo"
66
- YAML.expects(:load).with("foo").returns "bar"
66
+ YAML.expects(:safely_load).with("foo").returns "bar"
67
67
  @yaml.intern_multiple(String, text).should == "bar"
68
68
  end
69
69
  end
@@ -120,10 +120,10 @@ describe "Puppet Network Format" do
120
120
  @yaml.intern_multiple(String, text).should == "bar"
121
121
  end
122
122
 
123
- it "should decode by base64 decoding, uncompressing and Yaml loading" do
123
+ it "should decode by base64 decoding, uncompressing and safely Yaml loading" do
124
124
  Base64.expects(:decode64).with("zorg").returns "foo"
125
125
  Zlib::Inflate.expects(:inflate).with("foo").returns "baz"
126
- YAML.expects(:load).with("baz").returns "bar"
126
+ YAML.expects(:safely_load).with("baz").returns "bar"
127
127
  @yaml.decode("zorg").should == "bar"
128
128
  end
129
129
 
@@ -90,7 +90,6 @@ describe Puppet::Network::HTTP::Connection do
90
90
 
91
91
  it { should be_use_ssl }
92
92
  its(:cert) { should be_nil }
93
- its(:cert_store) { should be_nil }
94
93
  its(:ca_file) { should be_nil }
95
94
  its(:key) { should be_nil }
96
95
  its(:verify_mode) { should == OpenSSL::SSL::VERIFY_NONE }
@@ -137,6 +137,31 @@ describe Puppet::Network::HTTP::Handler do
137
137
  @handler.request_format(@request).should == "s"
138
138
  end
139
139
 
140
+ it "should deserialize YAML parameters" do
141
+ params = {'my_param' => [1,2,3].to_yaml}
142
+
143
+ decoded_params = @handler.send(:decode_params, params)
144
+
145
+ decoded_params.should == {:my_param => [1,2,3]}
146
+ end
147
+
148
+ it "should accept YAML parameters with !ruby/hash tags on Ruby 1.8", :if => RUBY_VERSION =~ /^1\.8/ do
149
+ params = {'my_param' => "--- !ruby/hash:Array {}"}
150
+
151
+ decoded_params = @handler.send(:decode_params, params)
152
+
153
+ decoded_params[:my_param].should be_an(Array)
154
+ end
155
+
156
+ # These are only dangerous with Psych, which is Ruby 1.9-only. Since
157
+ # there's no real way to change the yamler in Puppet, assume that 1.9 means
158
+ # Psych, especially in tests.
159
+ it "should fail if YAML parameters have !ruby/hash tags on Ruby 1.9", :unless => RUBY_VERSION =~ /^1\.8/ do
160
+ params = {'my_param' => "--- !ruby/hash:Array {}"}
161
+
162
+ expect { @handler.send(:decode_params, params) }.to raise_error(ArgumentError, /Illegal YAML mapping found/)
163
+ end
164
+
140
165
  describe "when finding a model instance" do
141
166
  before do
142
167
  @indirection.stubs(:find).returns @result
@@ -111,6 +111,23 @@ describe "Puppet::Network::HTTP::RackREST", :if => Puppet.features.rack? do
111
111
  @handler.set_response(@response, @file, 200)
112
112
  end
113
113
  end
114
+
115
+ it "should ensure the body has been read on success" do
116
+ req = mk_req('/production/report/foo', :method => 'PUT')
117
+ req.body.expects(:read).at_least_once
118
+
119
+ Puppet::Transaction::Report.stubs(:save)
120
+
121
+ @handler.process(req, @response)
122
+ end
123
+
124
+ it "should ensure the body has been partially read on failure" do
125
+ req = mk_req('/production/report/foo')
126
+ req.body.expects(:read).with(1)
127
+ req.stubs(:check_authorization).raises(Exception)
128
+
129
+ @handler.process(req, @response)
130
+ end
114
131
  end
115
132
 
116
133
  describe "and determining the request parameters" do
@@ -241,6 +241,10 @@ describe Puppet::Network::HTTP::WEBrick do
241
241
  server.setup_ssl[:SSLEnable].should be_true
242
242
  end
243
243
 
244
+ it "should reject SSLv2" do
245
+ server.setup_ssl[:SSLOptions].should == OpenSSL::SSL::OP_NO_SSLv2
246
+ end
247
+
244
248
  it "should configure the verification method as 'OpenSSL::SSL::VERIFY_PEER'" do
245
249
  server.setup_ssl[:SSLVerifyClient].should == OpenSSL::SSL::VERIFY_PEER
246
250
  end
@@ -6,58 +6,29 @@ describe "the inline_template function" do
6
6
  Puppet::Parser::Functions.autoloader.loadall
7
7
  end
8
8
 
9
- before :each do
10
- node = Puppet::Node.new('localhost')
11
- compiler = Puppet::Parser::Compiler.new(node)
12
- @scope = Puppet::Parser::Scope.new(compiler)
13
- end
14
-
15
- it "should exist" do
16
- Puppet::Parser::Functions.function("inline_template").should == "function_inline_template"
17
- end
18
-
19
- it "should create a TemplateWrapper when called" do
20
- tw = stub_everything 'template_wrapper'
9
+ let(:node) { Puppet::Node.new('localhost') }
10
+ let(:compiler) { Puppet::Parser::Compiler.new(node) }
11
+ let(:scope) { Puppet::Parser::Scope.new(compiler) }
21
12
 
22
- Puppet::Parser::TemplateWrapper.expects(:new).returns(tw)
23
-
24
- @scope.function_inline_template(["test"])
13
+ it "should concatenate template wrapper outputs for multiple templates" do
14
+ inline_template("template1", "template2").should == "template1template2"
25
15
  end
26
16
 
27
- it "should pass the template string to TemplateWrapper.result" do
28
- tw = stub_everything 'template_wrapper'
29
- Puppet::Parser::TemplateWrapper.stubs(:new).returns(tw)
30
-
31
- tw.expects(:result).with("test")
32
-
33
- @scope.function_inline_template(["test"])
17
+ it "should raise an error if the template raises an error" do
18
+ expect { inline_template("<% raise 'error' %>") }.to raise_error(Puppet::ParseError)
34
19
  end
35
20
 
36
- it "should return what TemplateWrapper.result returns" do
37
- tw = stub_everything 'template_wrapper'
38
- Puppet::Parser::TemplateWrapper.stubs(:new).returns(tw)
39
-
40
- tw.expects(:result).returns("template contents evaluated")
41
-
42
- @scope.function_inline_template(["test"]).should == "template contents evaluated"
21
+ it "is not interfered with by a variable called 'string' (#14093)" do
22
+ scope['string'] = "this is a variable"
23
+ inline_template("this is a template").should == "this is a template"
43
24
  end
44
25
 
45
- it "should concatenate template wrapper outputs for multiple templates" do
46
- tw1 = stub_everything "template_wrapper1"
47
- tw2 = stub_everything "template_wrapper2"
48
- Puppet::Parser::TemplateWrapper.stubs(:new).returns(tw1,tw2)
49
- tw1.stubs(:result).returns("result1")
50
- tw2.stubs(:result).returns("result2")
51
-
52
- @scope.function_inline_template(["1","2"]).should == "result1result2"
26
+ it "has access to a variable called 'string' (#14093)" do
27
+ scope['string'] = "this is a variable"
28
+ inline_template("string was: <%= @string %>").should == "string was: this is a variable"
53
29
  end
54
30
 
55
- it "should raise an error if the template raises an error" do
56
- tw = stub_everything 'template_wrapper'
57
- Puppet::Parser::TemplateWrapper.stubs(:new).returns(tw)
58
- tw.stubs(:result).raises
59
-
60
- lambda { @scope.function_inline_template(["1"]) }.should raise_error(Puppet::ParseError)
31
+ def inline_template(*templates)
32
+ scope.function_inline_template(templates)
61
33
  end
62
-
63
34
  end
@@ -10,38 +10,7 @@ describe "the template function" do
10
10
  let :compiler do Puppet::Parser::Compiler.new(node) end
11
11
  let :scope do Puppet::Parser::Scope.new(compiler) end
12
12
 
13
- it "should exist" do
14
- Puppet::Parser::Functions.function("template").should == "function_template"
15
- end
16
-
17
- it "should create a TemplateWrapper when called" do
18
- tw = stub_everything 'template_wrapper'
19
-
20
- Puppet::Parser::TemplateWrapper.expects(:new).returns(tw)
21
-
22
- scope.function_template(["test"])
23
- end
24
-
25
- it "should give the template filename to the TemplateWrapper" do
26
- tw = stub_everything 'template_wrapper'
27
- Puppet::Parser::TemplateWrapper.stubs(:new).returns(tw)
28
-
29
- tw.expects(:file=).with("test")
30
-
31
- scope.function_template(["test"])
32
- end
33
-
34
- it "should return what TemplateWrapper.result returns" do
35
- tw = stub_everything 'template_wrapper'
36
- Puppet::Parser::TemplateWrapper.stubs(:new).returns(tw)
37
- tw.stubs(:file=).with("test")
38
-
39
- tw.expects(:result).returns("template contents evaluated")
40
-
41
- scope.function_template(["test"]).should == "template contents evaluated"
42
- end
43
-
44
- it "should concatenate template wrapper outputs for multiple templates" do
13
+ it "concatenates outputs for multiple templates" do
45
14
  tw1 = stub_everything "template_wrapper1"
46
15
  tw2 = stub_everything "template_wrapper2"
47
16
  Puppet::Parser::TemplateWrapper.stubs(:new).returns(tw1,tw2)
@@ -53,7 +22,7 @@ describe "the template function" do
53
22
  scope.function_template(["1","2"]).should == "result1result2"
54
23
  end
55
24
 
56
- it "should raise an error if the template raises an error" do
25
+ it "raises an error if the template raises an error" do
57
26
  tw = stub_everything 'template_wrapper'
58
27
  Puppet::Parser::TemplateWrapper.stubs(:new).returns(tw)
59
28
  tw.stubs(:result).raises
@@ -63,40 +32,58 @@ describe "the template function" do
63
32
  }.to raise_error(Puppet::ParseError, /Failed to parse template/)
64
33
  end
65
34
 
66
- def eval_template(content, *rest)
67
- File.stubs(:read).with("template").returns(content)
68
- Puppet::Parser::Files.stubs(:find_template).returns("template")
69
- scope.function_template(['template'] + rest)
35
+ context "when accessing scope variables via method calls (deprecated)" do
36
+ it "raises an error when accessing an undefined variable" do
37
+ expect {
38
+ eval_template("template <%= deprecated %>")
39
+ }.to raise_error(Puppet::ParseError, /Could not find value for 'deprecated'/)
40
+ end
41
+
42
+ it "looks up the value from the scope" do
43
+ scope["deprecated"] = "deprecated value"
44
+ eval_template("template <%= deprecated %>").should == "template deprecated value"
45
+ end
46
+
47
+ it "still has access to Kernel methods" do
48
+ expect { eval_template("<%= binding %>") }.to_not raise_error
49
+ end
70
50
  end
71
51
 
72
- it "should handle legacy template variable access correctly" do
73
- expect {
74
- eval_template("template <%= deprecated %>")
75
- }.to raise_error(Puppet::ParseError)
52
+ context "when accessing scope variables as instance variables" do
53
+ it "has access to values" do
54
+ scope['scope_var'] = "value"
55
+ eval_template("<%= @scope_var %>").should == "value"
56
+ end
57
+
58
+ it "get nil accessing a variable that does not exist" do
59
+ eval_template("<%= @not_defined.nil? %>").should == "true"
60
+ end
61
+
62
+ it "get nil accessing a variable that is undef" do
63
+ scope['undef_var'] = :undef
64
+ eval_template("<%= @undef_var.nil? %>").should == "true"
65
+ end
76
66
  end
77
67
 
78
- it "should get values from the scope correctly" do
79
- scope["deprecated"] = "deprecated value"
80
- eval_template("template <%= deprecated %>").should == "template deprecated value"
68
+ it "is not interfered with by having a variable named 'string' (#14093)" do
69
+ scope['string'] = "this output should not be seen"
70
+ eval_template("some text that is static").should == "some text that is static"
81
71
  end
82
72
 
83
- it "should handle kernel shadows without raising" do
84
- expect { eval_template("<%= binding %>") }.to_not raise_error
73
+ it "has access to a variable named 'string' (#14093)" do
74
+ scope['string'] = "the string value"
75
+ eval_template("string was: <%= @string %>").should == "string was: the string value"
85
76
  end
86
77
 
87
- it "should not see scopes" do
88
- scope['myvar'] = 'this is yayness'
78
+ it "does not have direct access to Scope#lookupvar" do
89
79
  expect {
90
80
  eval_template("<%= lookupvar('myvar') %>")
91
- }.to raise_error(Puppet::ParseError)
81
+ }.to raise_error(Puppet::ParseError, /Could not find value for 'lookupvar'/)
92
82
  end
93
83
 
94
- { "" => "", false => "false", true => "true" }.each do |input, output|
95
- it "should support defined variables (#{input.inspect} => #{output.inspect})" do
96
- scope['yayness'] = input
97
- expect {
98
- eval_template("<%= @yayness %>").should == output
99
- }.to_not raise_error
100
- end
84
+ def eval_template(content)
85
+ File.stubs(:read).with("template").returns(content)
86
+ Puppet::Parser::Files.stubs(:find_template).returns("template")
87
+ scope.function_template(['template'])
101
88
  end
102
89
  end