puppet 4.10.1-universal-darwin → 4.10.4-universal-darwin
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.
- data/ext/project_data.yaml +1 -1
- data/lib/puppet.rb +40 -28
- data/lib/puppet/application/agent.rb +1 -1
- data/lib/puppet/application/apply.rb +1 -1
- data/lib/puppet/application/cert.rb +1 -1
- data/lib/puppet/application/describe.rb +1 -1
- data/lib/puppet/application/device.rb +1 -1
- data/lib/puppet/application/doc.rb +3 -3
- data/lib/puppet/application/filebucket.rb +1 -1
- data/lib/puppet/application/inspect.rb +2 -2
- data/lib/puppet/application/lookup.rb +1 -1
- data/lib/puppet/application/master.rb +1 -1
- data/lib/puppet/application/resource.rb +7 -7
- data/lib/puppet/defaults.rb +1 -1
- data/lib/puppet/etc.rb +75 -39
- data/lib/puppet/face/ca.rb +1 -1
- data/lib/puppet/face/catalog.rb +1 -1
- data/lib/puppet/face/certificate.rb +1 -1
- data/lib/puppet/face/certificate_request.rb +1 -1
- data/lib/puppet/face/certificate_revocation_list.rb +1 -1
- data/lib/puppet/face/config.rb +1 -1
- data/lib/puppet/face/epp.rb +1 -1
- data/lib/puppet/face/facts.rb +1 -1
- data/lib/puppet/face/file.rb +1 -1
- data/lib/puppet/face/help.rb +1 -1
- data/lib/puppet/face/key.rb +1 -1
- data/lib/puppet/face/man.rb +2 -2
- data/lib/puppet/face/module.rb +1 -1
- data/lib/puppet/face/node.rb +1 -1
- data/lib/puppet/face/parser.rb +1 -1
- data/lib/puppet/face/plugin.rb +1 -1
- data/lib/puppet/face/report.rb +1 -1
- data/lib/puppet/face/resource.rb +1 -1
- data/lib/puppet/face/resource_type.rb +1 -1
- data/lib/puppet/face/status.rb +1 -1
- data/lib/puppet/feature/base.rb +1 -1
- data/lib/puppet/functions/eyaml_lookup_key.rb +16 -12
- data/lib/puppet/functions/hiera.rb +9 -2
- data/lib/puppet/functions/hiera_array.rb +9 -2
- data/lib/puppet/functions/hiera_hash.rb +10 -2
- data/lib/puppet/functions/hiera_include.rb +17 -3
- data/lib/puppet/functions/hocon_data.rb +6 -0
- data/lib/puppet/functions/json_data.rb +4 -0
- data/lib/puppet/functions/yaml_data.rb +4 -0
- data/lib/puppet/generate/models/type/type.rb +6 -5
- data/lib/puppet/generate/templates/type/pcore.erb +1 -1
- data/lib/puppet/module_tool/skeleton/templates/generator/examples/init.pp.erb +1 -1
- data/lib/puppet/parser/functions/create_resources.rb +8 -0
- data/lib/puppet/parser/scope.rb +2 -2
- data/lib/puppet/pops/adapters.rb +10 -4
- data/lib/puppet/pops/evaluator/runtime3_resource_support.rb +0 -2
- data/lib/puppet/pops/evaluator/runtime3_support.rb +31 -0
- data/lib/puppet/pops/issues.rb +8 -0
- data/lib/puppet/pops/loader/loader.rb +4 -0
- data/lib/puppet/pops/loader/module_loaders.rb +0 -2
- data/lib/puppet/pops/loader/static_loader.rb +1 -1
- data/lib/puppet/pops/loader/type_definition_instantiator.rb +1 -1
- data/lib/puppet/pops/loader/typed_name.rb +1 -0
- data/lib/puppet/pops/loaders.rb +7 -15
- data/lib/puppet/pops/lookup/environment_data_provider.rb +1 -1
- data/lib/puppet/pops/lookup/hiera_config.rb +3 -1
- data/lib/puppet/pops/lookup/interpolation.rb +2 -1
- data/lib/puppet/pops/lookup/lookup_key.rb +1 -1
- data/lib/puppet/pops/lookup/module_data_provider.rb +10 -2
- data/lib/puppet/pops/lookup/sub_lookup.rb +10 -9
- data/lib/puppet/pops/parser/lexer2.rb +20 -3
- data/lib/puppet/pops/pcore.rb +2 -2
- data/lib/puppet/pops/resource/resource_type_impl.rb +2 -2
- data/lib/puppet/pops/semantic_error.rb +12 -0
- data/lib/puppet/pops/serialization/deserializer.rb +7 -4
- data/lib/puppet/pops/types/p_type_set_type.rb +2 -2
- data/lib/puppet/pops/types/string_converter.rb +5 -17
- data/lib/puppet/pops/types/type_set_reference.rb +1 -1
- data/lib/puppet/pops/validation/checker4_0.rb +4 -0
- data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -0
- data/lib/puppet/provider/nameservice.rb +12 -4
- data/lib/puppet/provider/package/yum.rb +8 -8
- data/lib/puppet/provider/user/useradd.rb +1 -1
- data/lib/puppet/reference/configuration.rb +1 -1
- data/lib/puppet/resource.rb +9 -11
- data/lib/puppet/resource/type_collection.rb +1 -0
- data/lib/puppet/type/exec.rb +32 -26
- data/lib/puppet/type/file/mode.rb +4 -0
- data/lib/puppet/util/character_encoding.rb +77 -74
- data/lib/puppet/util/monkey_patches.rb +3 -1
- data/lib/puppet/util/windows/api_types.rb +3 -0
- data/lib/puppet/util/windows/file.rb +1 -1
- data/lib/puppet/version.rb +1 -1
- data/locales/puppet.pot +31 -7
- data/spec/integration/faces/documentation_spec.rb +2 -2
- data/spec/integration/parser/pcore_resource_spec.rb +15 -0
- data/spec/integration/resource/type_collection_spec.rb +6 -0
- data/spec/lib/puppet/face/1.0.0/huzzah.rb +1 -1
- data/spec/lib/puppet/face/basetest.rb +1 -1
- data/spec/lib/puppet/face/huzzah.rb +1 -1
- data/spec/lib/puppet/face/version_matching.rb +1 -1
- data/spec/lib/puppet_spec/character_encoding.rb +12 -0
- data/spec/lib/puppet_spec/compiler.rb +7 -0
- data/spec/shared_examples/rhel_package_provider.rb +10 -11
- data/spec/unit/application/resource_spec.rb +22 -1
- data/spec/unit/configurer/fact_handler_spec.rb +2 -1
- data/spec/unit/etc_spec.rb +361 -153
- data/spec/unit/functions/lookup_spec.rb +118 -2
- data/spec/unit/parser/functions/create_resources_spec.rb +47 -6
- data/spec/unit/parser/scope_spec.rb +8 -0
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +40 -0
- data/spec/unit/pops/loaders/loaders_spec.rb +141 -79
- data/spec/unit/pops/lookup/interpolation_spec.rb +49 -9
- data/spec/unit/pops/lookup/lookup_spec.rb +32 -0
- data/spec/unit/pops/parser/lexer2_spec.rb +28 -0
- data/spec/unit/pops/types/p_object_type_spec.rb +1 -1
- data/spec/unit/pops/types/p_type_set_type_spec.rb +1 -1
- data/spec/unit/pops/types/string_converter_spec.rb +21 -0
- data/spec/unit/pops/validator/validator_spec.rb +43 -0
- data/spec/unit/provider/nameservice/directoryservice_spec.rb +2 -0
- data/spec/unit/provider/nameservice_spec.rb +113 -3
- data/spec/unit/provider/user/useradd_spec.rb +13 -0
- data/spec/unit/resource/catalog_spec.rb +21 -0
- data/spec/unit/util/character_encoding_spec.rb +193 -52
- metadata +4 -2
@@ -6,28 +6,57 @@ module Puppet::Pops
|
|
6
6
|
describe 'Puppet::Pops::Lookup::Interpolation' do
|
7
7
|
include Lookup::SubLookup
|
8
8
|
|
9
|
+
class InterpolationTestAdapter < Lookup::LookupAdapter
|
10
|
+
include Lookup::SubLookup
|
11
|
+
|
12
|
+
def initialize(data, interpolator)
|
13
|
+
@data = data
|
14
|
+
@interpolator = interpolator
|
15
|
+
end
|
16
|
+
|
17
|
+
def track(name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def lookup(name, lookup_invocation, merge)
|
21
|
+
track(name)
|
22
|
+
segments = split_key(name)
|
23
|
+
root_key = segments.shift
|
24
|
+
found = @data[root_key]
|
25
|
+
found = sub_lookup(name, lookup_invocation, segments, found) unless segments.empty?
|
26
|
+
@interpolator.interpolate(found, lookup_invocation, true)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
9
30
|
let(:interpolator) { Class.new { include Lookup::Interpolation }.new }
|
10
31
|
let(:scope) { {} }
|
32
|
+
let(:data) { {} }
|
33
|
+
let(:adapter) { InterpolationTestAdapter.new(data, interpolator) }
|
11
34
|
let(:lookup_invocation) { Lookup::Invocation.new(scope, {}, {}, nil) }
|
12
35
|
|
36
|
+
before(:each) do
|
37
|
+
Lookup::Invocation.any_instance.stubs(:lookup_adapter).returns(adapter)
|
38
|
+
end
|
39
|
+
|
13
40
|
def expect_lookup(*keys)
|
14
|
-
keys.each
|
15
|
-
segments = split_key(key)
|
16
|
-
root_key = segments.shift
|
17
|
-
found = data[root_key]
|
18
|
-
found = sub_lookup(key, lookup_invocation, segments, found) unless segments.empty?
|
19
|
-
Lookup.expects(:lookup).with(key, nil, '', true, nil, is_a(Lookup::Invocation)).returns(found)
|
20
|
-
end
|
41
|
+
keys.each { |key| adapter.expects(:track).with(key) }
|
21
42
|
end
|
22
43
|
|
23
44
|
context 'when interpolating nested data' do
|
24
45
|
let(:nested_hash) { {'a' => {'aa' => "%{alias('aaa')}"}} }
|
25
46
|
|
47
|
+
let(:scope) {
|
48
|
+
{
|
49
|
+
'ds1' => 'a',
|
50
|
+
'ds2' => 'b'
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
26
54
|
let(:data) {
|
27
55
|
{
|
28
56
|
'aaa' => {'b' => {'bb' => "%{alias('bbb')}"}},
|
29
57
|
'bbb' => ["%{alias('ccc')}"],
|
30
|
-
'ccc' => 'text'
|
58
|
+
'ccc' => 'text',
|
59
|
+
'ddd' => "%{literal('%')}{ds1}_%{literal('%')}{ds2}",
|
31
60
|
}
|
32
61
|
}
|
33
62
|
|
@@ -35,6 +64,16 @@ describe 'Puppet::Pops::Lookup::Interpolation' do
|
|
35
64
|
expect_lookup('aaa', 'bbb', 'ccc')
|
36
65
|
expect(interpolator.interpolate(nested_hash, lookup_invocation, true)).to eq('a' => {'aa' => {'b' => {'bb' => ['text']}}})
|
37
66
|
end
|
67
|
+
|
68
|
+
it "'%{lookup('key')} will interpolate the returned value'" do
|
69
|
+
expect_lookup('ddd')
|
70
|
+
expect(interpolator.interpolate("%{lookup('ddd')}", lookup_invocation, true)).to eq('a_b')
|
71
|
+
end
|
72
|
+
|
73
|
+
it "'%{alias('key')} will not interpolate the returned value'" do
|
74
|
+
expect_lookup('ddd')
|
75
|
+
expect(interpolator.interpolate("%{alias('ddd')}", lookup_invocation, true)).to eq('%{ds1}_%{ds2}')
|
76
|
+
end
|
38
77
|
end
|
39
78
|
|
40
79
|
context 'when interpolating boolean scope values' do
|
@@ -242,7 +281,8 @@ describe 'Puppet::Pops::Lookup::Interpolation' do
|
|
242
281
|
end
|
243
282
|
|
244
283
|
it 'should not find a subkey that is matched within a string' do
|
245
|
-
expect{
|
284
|
+
expect{ interpolator.interpolate("%{lookup('key.subkey')}", lookup_invocation, true) }.to raise_error(
|
285
|
+
/Got String when a hash-like object was expected to access value using 'subkey' from key 'key.subkey'/)
|
246
286
|
end
|
247
287
|
end
|
248
288
|
|
@@ -57,6 +57,13 @@ describe 'The lookup API' do
|
|
57
57
|
mod::c: mod::c (from module)
|
58
58
|
mod::e: mod::e (from module)
|
59
59
|
mod::f: mod::f (from module)
|
60
|
+
mod::g:
|
61
|
+
:symbol: symbol key value
|
62
|
+
key: string key value
|
63
|
+
6: integer key value
|
64
|
+
-4: negative integer key value
|
65
|
+
2.7: float key value
|
66
|
+
'6': string integer key value
|
60
67
|
YAML
|
61
68
|
}
|
62
69
|
}
|
@@ -137,6 +144,31 @@ describe 'The lookup API' do
|
|
137
144
|
expect(Lookup.lookup('mod::f', nil, 'not found', true, nil, invocation)).to eql('mod::f (from environment)')
|
138
145
|
end
|
139
146
|
|
147
|
+
it 'returns the correct types for hash keys' do
|
148
|
+
expect(Lookup.lookup('mod::g', nil, 'not found', true, nil, invocation)).to eql(
|
149
|
+
{
|
150
|
+
'symbol' => 'symbol key value',
|
151
|
+
'key' => 'string key value',
|
152
|
+
6 => 'integer key value',
|
153
|
+
-4 => 'negative integer key value',
|
154
|
+
2.7 => 'float key value',
|
155
|
+
'6' => 'string integer key value'
|
156
|
+
}
|
157
|
+
)
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'can navigate a hash with an integer key using a dotted key' do
|
161
|
+
expect(Lookup.lookup('mod::g.6', nil, 'not found', true, nil, invocation)).to eql('integer key value')
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'can navigate a hash with a negative integer key using a dotted key' do
|
165
|
+
expect(Lookup.lookup('mod::g.-4', nil, 'not found', true, nil, invocation)).to eql('negative integer key value')
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'can navigate a hash with an string integer key using a dotted key with quoted integer' do
|
169
|
+
expect(Lookup.lookup("mod::g.'6'", nil, 'not found', true, nil, invocation)).to eql('string integer key value')
|
170
|
+
end
|
171
|
+
|
140
172
|
context "with 'global_only' set to true in the invocation" do
|
141
173
|
let(:invocation) { Invocation.new(scope).set_global_only }
|
142
174
|
|
@@ -412,6 +412,34 @@ describe 'Lexer2' do
|
|
412
412
|
expect(tokens_scanned_from("1 / /./")).to match_tokens2(:NUMBER, :DIV, :REGEX)
|
413
413
|
end
|
414
414
|
|
415
|
+
it 'should lex regexp with escaped slash' do
|
416
|
+
scanned = tokens_scanned_from('/\//')
|
417
|
+
expect(scanned).to match_tokens2(:REGEX)
|
418
|
+
expect(scanned[0][1][:value]).to eql(Regexp.new('/'))
|
419
|
+
end
|
420
|
+
|
421
|
+
it 'should lex regexp with escaped backslash' do
|
422
|
+
scanned = tokens_scanned_from('/\\\\/')
|
423
|
+
expect(scanned).to match_tokens2(:REGEX)
|
424
|
+
expect(scanned[0][1][:value]).to eql(Regexp.new('\\\\'))
|
425
|
+
end
|
426
|
+
|
427
|
+
it 'should lex regexp with escaped backslash followed escaped slash ' do
|
428
|
+
scanned = tokens_scanned_from('/\\\\\\//')
|
429
|
+
expect(scanned).to match_tokens2(:REGEX)
|
430
|
+
expect(scanned[0][1][:value]).to eql(Regexp.new('\\\\/'))
|
431
|
+
end
|
432
|
+
|
433
|
+
it 'should lex regexp with escaped slash followed escaped backslash ' do
|
434
|
+
scanned = tokens_scanned_from('/\\/\\\\/')
|
435
|
+
expect(scanned).to match_tokens2(:REGEX)
|
436
|
+
expect(scanned[0][1][:value]).to eql(Regexp.new('/\\\\'))
|
437
|
+
end
|
438
|
+
|
439
|
+
it 'should not lex regexp with escaped ending slash' do
|
440
|
+
expect(tokens_scanned_from('/\\/')).to match_tokens2(:DIV, :OTHER, :DIV)
|
441
|
+
end
|
442
|
+
|
415
443
|
it "should accept newline in a regular expression" do
|
416
444
|
scanned = tokens_scanned_from("/\n.\n/")
|
417
445
|
# Note that strange formatting here is important
|
@@ -20,7 +20,7 @@ describe 'The Object Type' do
|
|
20
20
|
|
21
21
|
def type_object_t(name, body_string)
|
22
22
|
object = PObjectType.new(name, pp_parser.parse_string("{#{body_string}}").current.body)
|
23
|
-
loader.set_entry(Loader::TypedName.new(:type, name
|
23
|
+
loader.set_entry(Loader::TypedName.new(:type, name), object)
|
24
24
|
object
|
25
25
|
end
|
26
26
|
|
@@ -16,7 +16,7 @@ module Puppet::Pops
|
|
16
16
|
def type_set_t(name, body_string, name_authority)
|
17
17
|
i12n_literal_hash = pp_parser.parse_string("{#{body_string}}").current.body
|
18
18
|
typeset = PTypeSetType.new(name, i12n_literal_hash, name_authority)
|
19
|
-
loader.set_entry(Loader::TypedName.new(:type, name
|
19
|
+
loader.set_entry(Loader::TypedName.new(:type, name, name_authority), typeset)
|
20
20
|
typeset
|
21
21
|
end
|
22
22
|
|
@@ -874,6 +874,22 @@ describe 'The string converter' do
|
|
874
874
|
end
|
875
875
|
end
|
876
876
|
|
877
|
+
context 'when converting a runtime type' do
|
878
|
+
[ :sym, (1..3), Time.now ].each do |value|
|
879
|
+
it "the default string representation for #{value} is #to_s" do
|
880
|
+
expect(converter.convert(value, :default)).to eq(value.to_s)
|
881
|
+
end
|
882
|
+
|
883
|
+
it "the '%q' string representation for #{value} is #inspect" do
|
884
|
+
expect(converter.convert(value, '%q')).to eq(value.inspect)
|
885
|
+
end
|
886
|
+
end
|
887
|
+
|
888
|
+
it 'an unknown format raises an error' do
|
889
|
+
expect { converter.convert(:sym, '%b') }.to raise_error("Illegal format 'b' specified for value of Runtime type - expected one of the characters 'sq'")
|
890
|
+
end
|
891
|
+
end
|
892
|
+
|
877
893
|
context 'when converting regexp' do
|
878
894
|
it 'the default string representation is "regexp"' do
|
879
895
|
expect(converter.convert(/.*/, :default)).to eq('.*')
|
@@ -906,6 +922,11 @@ describe 'The string converter' do
|
|
906
922
|
string_formats = { Puppet::Pops::Types::PRegexpType::DEFAULT => '%p'}
|
907
923
|
expect(converter.convert(/[a-z]\s*/m, string_formats)).to eq('/(?m-ix:[a-z]\s*)/')
|
908
924
|
end
|
925
|
+
|
926
|
+
it 'the format %p produces \'/foo\/bar/\' for expression /foo\/bar/' do
|
927
|
+
string_formats = { Puppet::Pops::Types::PRegexpType::DEFAULT => '%p'}
|
928
|
+
expect(converter.convert(/foo\/bar/, string_formats)).to eq('/foo\/bar/')
|
929
|
+
end
|
909
930
|
end
|
910
931
|
|
911
932
|
it 'errors when format is not recognized' do
|
@@ -94,6 +94,21 @@ describe "validating 4x" do
|
|
94
94
|
expect(acceptor.error_count).to eql(0)
|
95
95
|
expect(acceptor).to have_issue(Puppet::Pops::Issues::DUPLICATE_DEFAULT)
|
96
96
|
end
|
97
|
+
|
98
|
+
it 'produces a warning for virtual class resource' do
|
99
|
+
acceptor = validate(parse('@class { test: }'))
|
100
|
+
expect(acceptor.warning_count).to eql(1)
|
101
|
+
expect(acceptor.error_count).to eql(0)
|
102
|
+
expect(acceptor).to have_issue(Puppet::Pops::Issues::CLASS_NOT_VIRTUALIZABLE)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'produces a warning for exported class resource' do
|
106
|
+
acceptor = validate(parse('@@class { test: }'))
|
107
|
+
expect(acceptor.warning_count).to eql(1)
|
108
|
+
expect(acceptor.error_count).to eql(0)
|
109
|
+
expect(acceptor).to have_issue(Puppet::Pops::Issues::CLASS_NOT_VIRTUALIZABLE)
|
110
|
+
end
|
111
|
+
|
97
112
|
end
|
98
113
|
|
99
114
|
context 'with --strict set to error' do
|
@@ -118,6 +133,20 @@ describe "validating 4x" do
|
|
118
133
|
expect(acceptor.error_count).to eql(1)
|
119
134
|
expect(acceptor).to have_issue(Puppet::Pops::Issues::DUPLICATE_DEFAULT)
|
120
135
|
end
|
136
|
+
|
137
|
+
it 'produces an error for virtual class resource' do
|
138
|
+
acceptor = validate(parse('@class { test: }'))
|
139
|
+
expect(acceptor.warning_count).to eql(0)
|
140
|
+
expect(acceptor.error_count).to eql(1)
|
141
|
+
expect(acceptor).to have_issue(Puppet::Pops::Issues::CLASS_NOT_VIRTUALIZABLE)
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'produces an error for exported class resource' do
|
145
|
+
acceptor = validate(parse('@@class { test: }'))
|
146
|
+
expect(acceptor.warning_count).to eql(0)
|
147
|
+
expect(acceptor.error_count).to eql(1)
|
148
|
+
expect(acceptor).to have_issue(Puppet::Pops::Issues::CLASS_NOT_VIRTUALIZABLE)
|
149
|
+
end
|
121
150
|
end
|
122
151
|
|
123
152
|
context 'with --strict set to off' do
|
@@ -142,6 +171,20 @@ describe "validating 4x" do
|
|
142
171
|
expect(acceptor.error_count).to eql(0)
|
143
172
|
expect(acceptor).to_not have_issue(Puppet::Pops::Issues::DUPLICATE_DEFAULT)
|
144
173
|
end
|
174
|
+
|
175
|
+
it 'produces a warning for virtual class resource' do
|
176
|
+
acceptor = validate(parse('@class { test: }'))
|
177
|
+
expect(acceptor.warning_count).to eql(1)
|
178
|
+
expect(acceptor.error_count).to eql(0)
|
179
|
+
expect(acceptor).to have_issue(Puppet::Pops::Issues::CLASS_NOT_VIRTUALIZABLE)
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'produces a warning for exported class resource' do
|
183
|
+
acceptor = validate(parse('@@class { test: }'))
|
184
|
+
expect(acceptor.warning_count).to eql(1)
|
185
|
+
expect(acceptor.error_count).to eql(0)
|
186
|
+
expect(acceptor).to have_issue(Puppet::Pops::Issues::CLASS_NOT_VIRTUALIZABLE)
|
187
|
+
end
|
145
188
|
end
|
146
189
|
|
147
190
|
context 'for non productive expressions' do
|
@@ -11,6 +11,7 @@ end
|
|
11
11
|
describe provider_class do
|
12
12
|
before do
|
13
13
|
@resource = stub("resource")
|
14
|
+
@resource.stubs(:[]).with(:name)
|
14
15
|
@provider = provider_class.new(@resource)
|
15
16
|
end
|
16
17
|
|
@@ -143,6 +144,7 @@ describe '(#4855) directoryservice group resource failure' do
|
|
143
144
|
|
144
145
|
before :each do
|
145
146
|
@resource = stub("resource")
|
147
|
+
@resource.stubs(:[]).with(:name)
|
146
148
|
@provider = provider_class.new(@resource)
|
147
149
|
end
|
148
150
|
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
require 'puppet/provider/nameservice'
|
5
5
|
require 'puppet/etc'
|
6
|
+
require 'puppet_spec/character_encoding'
|
6
7
|
|
7
8
|
describe Puppet::Provider::NameService do
|
8
9
|
|
@@ -60,6 +61,36 @@ describe Puppet::Provider::NameService do
|
|
60
61
|
resource
|
61
62
|
end
|
62
63
|
|
64
|
+
# These values simulate what Ruby Etc would return from a host with the "same"
|
65
|
+
# user represented in different encodings on disk.
|
66
|
+
let(:utf_8_jose) { "Jos\u00E9"}
|
67
|
+
let(:utf_8_labeled_as_latin_1_jose) { utf_8_jose.dup.force_encoding(Encoding::ISO_8859_1) }
|
68
|
+
let(:valid_latin1_jose) { utf_8_jose.encode(Encoding::ISO_8859_1)}
|
69
|
+
let(:invalid_utf_8_jose) { valid_latin1_jose.dup.force_encoding(Encoding::UTF_8) }
|
70
|
+
let(:escaped_utf_8_jose) { "Jos\uFFFD".force_encoding(Encoding::UTF_8) }
|
71
|
+
|
72
|
+
let(:utf_8_mixed_users) {
|
73
|
+
[
|
74
|
+
Struct::Passwd.new('root', 'x', 0, 0),
|
75
|
+
Struct::Passwd.new('foo', 'x', 1000, 2000),
|
76
|
+
Struct::Passwd.new(utf_8_jose, utf_8_jose, 1001, 2000), # UTF-8 character
|
77
|
+
# In a UTF-8 environment, ruby will return strings labeled as UTF-8 even if they're not valid in UTF-8
|
78
|
+
Struct::Passwd.new(invalid_utf_8_jose, invalid_utf_8_jose, 1002, 2000),
|
79
|
+
nil
|
80
|
+
]
|
81
|
+
}
|
82
|
+
|
83
|
+
let(:latin_1_mixed_users) {
|
84
|
+
[
|
85
|
+
# In a LATIN-1 environment, ruby will return *all* strings labeled as LATIN-1
|
86
|
+
Struct::Passwd.new('root'.force_encoding(Encoding::ISO_8859_1), 'x', 0, 0),
|
87
|
+
Struct::Passwd.new('foo'.force_encoding(Encoding::ISO_8859_1), 'x', 1000, 2000),
|
88
|
+
Struct::Passwd.new(utf_8_labeled_as_latin_1_jose, utf_8_labeled_as_latin_1_jose, 1002, 2000),
|
89
|
+
Struct::Passwd.new(valid_latin1_jose, valid_latin1_jose, 1001, 2000), # UTF-8 character
|
90
|
+
nil
|
91
|
+
]
|
92
|
+
}
|
93
|
+
|
63
94
|
describe "#options" do
|
64
95
|
it "should add options for a valid property" do
|
65
96
|
described_class.options :foo, :key1 => 'val1', :key2 => 'val2'
|
@@ -121,6 +152,11 @@ describe Puppet::Provider::NameService do
|
|
121
152
|
end
|
122
153
|
|
123
154
|
describe "#listbyname" do
|
155
|
+
it "should be deprecated" do
|
156
|
+
Puppet.expects(:deprecation_warning).with(regexp_matches(/listbyname is deprecated/))
|
157
|
+
described_class.listbyname
|
158
|
+
end
|
159
|
+
|
124
160
|
it "should return a list of users if resource_type is user" do
|
125
161
|
described_class.resource_type = Puppet::Type.type(:user)
|
126
162
|
Puppet::Etc.expects(:setpwent)
|
@@ -129,6 +165,30 @@ describe Puppet::Provider::NameService do
|
|
129
165
|
expect(described_class.listbyname).to eq(%w{root foo})
|
130
166
|
end
|
131
167
|
|
168
|
+
context "encoding handling" do
|
169
|
+
described_class.resource_type = Puppet::Type.type(:user)
|
170
|
+
|
171
|
+
# These two tests simulate an environment where there are two users with
|
172
|
+
# the same name on disk, but each name is stored on disk in a different
|
173
|
+
# encoding
|
174
|
+
it "should return names with invalid byte sequences replaced with '?'" do
|
175
|
+
Etc.stubs(:getpwent).returns *utf_8_mixed_users
|
176
|
+
expect(invalid_utf_8_jose).to_not be_valid_encoding
|
177
|
+
result = PuppetSpec::CharacterEncoding.with_external_encoding(Encoding::UTF_8) do
|
178
|
+
described_class.listbyname
|
179
|
+
end
|
180
|
+
expect(result).to eq(['root', 'foo', utf_8_jose, escaped_utf_8_jose])
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should return names in their original encoding/bytes if they would not be valid UTF-8" do
|
184
|
+
Etc.stubs(:getpwent).returns *latin_1_mixed_users
|
185
|
+
result = PuppetSpec::CharacterEncoding.with_external_encoding(Encoding::ISO_8859_1) do
|
186
|
+
described_class.listbyname
|
187
|
+
end
|
188
|
+
expect(result).to eq(['root'.force_encoding(Encoding::UTF_8), 'foo'.force_encoding(Encoding::UTF_8), utf_8_jose, valid_latin1_jose])
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
132
192
|
it "should return a list of groups if resource_type is group", :unless => Puppet.features.microsoft_windows? do
|
133
193
|
described_class.resource_type = Puppet::Type.type(:group)
|
134
194
|
Puppet::Etc.expects(:setgrent)
|
@@ -149,9 +209,44 @@ describe Puppet::Provider::NameService do
|
|
149
209
|
end
|
150
210
|
|
151
211
|
describe "instances" do
|
152
|
-
it "should return a list of objects
|
153
|
-
|
154
|
-
|
212
|
+
it "should return a list of objects in UTF-8 with any invalid characters replaced with '?'" do
|
213
|
+
# These two tests simulate an environment where there are two users with
|
214
|
+
# the same name on disk, but each name is stored on disk in a different
|
215
|
+
# encoding
|
216
|
+
Etc.stubs(:getpwent).returns(*utf_8_mixed_users)
|
217
|
+
result = PuppetSpec::CharacterEncoding.with_external_encoding(Encoding::UTF_8) do
|
218
|
+
described_class.instances
|
219
|
+
end
|
220
|
+
expect(result.map(&:name)).to eq(
|
221
|
+
[
|
222
|
+
'root'.force_encoding(Encoding::UTF_8), # started as UTF-8 on disk, returned unaltered as UTF-8
|
223
|
+
'foo'.force_encoding(Encoding::UTF_8), # started as UTF-8 on disk, returned unaltered as UTF-8
|
224
|
+
utf_8_jose, # started as UTF-8 on disk, returned unaltered as UTF-8
|
225
|
+
escaped_utf_8_jose # started as LATIN-1 on disk, but Etc returned as UTF-8 and we escaped invalid chars
|
226
|
+
]
|
227
|
+
)
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should have object names in their original encoding/bytes if they would not be valid UTF-8" do
|
231
|
+
Etc.stubs(:getpwent).returns(*latin_1_mixed_users)
|
232
|
+
result = PuppetSpec::CharacterEncoding.with_external_encoding(Encoding::ISO_8859_1) do
|
233
|
+
described_class.instances
|
234
|
+
end
|
235
|
+
expect(result.map(&:name)).to eq(
|
236
|
+
[
|
237
|
+
'root'.force_encoding(Encoding::UTF_8), # started as LATIN-1 on disk, we overrode to UTF-8
|
238
|
+
'foo'.force_encoding(Encoding::UTF_8), # started as LATIN-1 on disk, we overrode to UTF-8
|
239
|
+
utf_8_jose, # started as UTF-8 on disk, returned by Etc as LATIN-1, and we overrode to UTF-8
|
240
|
+
valid_latin1_jose # started as LATIN-1 on disk, returned by Etc as valid LATIN-1, and we leave as LATIN-1
|
241
|
+
]
|
242
|
+
)
|
243
|
+
end
|
244
|
+
|
245
|
+
it "should pass the Puppet::Etc :canonical_name Struct member to the constructor" do
|
246
|
+
users = [ Struct::Passwd.new(invalid_utf_8_jose, invalid_utf_8_jose, 1002, 2000), nil ]
|
247
|
+
Etc.stubs(:getpwent).returns(*users)
|
248
|
+
described_class.expects(:new).with(:name => escaped_utf_8_jose, :canonical_name => invalid_utf_8_jose, :ensure => :present)
|
249
|
+
described_class.instances
|
155
250
|
end
|
156
251
|
end
|
157
252
|
|
@@ -198,6 +293,21 @@ describe Puppet::Provider::NameService do
|
|
198
293
|
provider.expects(:info2hash).never
|
199
294
|
expect(provider.getinfo(true)).to be_nil
|
200
295
|
end
|
296
|
+
|
297
|
+
# Nameservice instances track the original resource name on disk, before
|
298
|
+
# overriding to UTF-8, in @canonical_name for querying that state on disk
|
299
|
+
# again if needed
|
300
|
+
it "should use the instance's @canonical_name to query the system" do
|
301
|
+
provider_instance = described_class.new(:name => 'foo', :canonical_name => 'original_foo', :ensure => :present)
|
302
|
+
Puppet::Etc.expects(:send).with(:getfoonam, 'original_foo')
|
303
|
+
provider_instance.getinfo(true)
|
304
|
+
end
|
305
|
+
|
306
|
+
it "should use the instance's name instead of canonical_name if not supplied during instantiation" do
|
307
|
+
provider_instance = described_class.new(:name => 'foo', :ensure => :present)
|
308
|
+
Puppet::Etc.expects(:send).with(:getfoonam, 'foo')
|
309
|
+
provider_instance.getinfo(true)
|
310
|
+
end
|
201
311
|
end
|
202
312
|
|
203
313
|
describe "info2hash" do
|