Skip to content

Commit 7ab1d9e

Browse files
committed
(MODULES-9428) Pass through full composite namevar values for simple_get_filter
To make sure that `simple_get_filter` can work for types with composite namevars, we need to pass through the full set of namevar values, since `resource_hash[type_definition.namevars.first]` is not enough for the provider to return an instance. When a provider implements `simple_get_filter`, and composite namevars, the Resource API does not provide sufficient information to `get` to retrieve the required resource state: ``` Puppet::ResourceApi.register_type( name: 'gpgkey', docs: <<-EOS, This type provides Puppet with the capabilities to manage ... EOS title_patterns: [ { pattern: %r{^(?<gpgdir>.*)/(?<name>[^/]*)$}, desc: 'Where the gpgdir and the key_name is provided as the last field of the path', }, { pattern: %r{^(?<name>.*)$}, desc: 'Where only the key_name is provided, if using the default folder', }, ], features: ['simple_get_filter'], attributes: { ensure: { type: 'Enum[present, absent]', desc: 'Whether this resource should be present or absent on the target system.', default: 'present', }, name: { type: 'String', desc: 'The name of the resource you want to manage.', behaviour: :namevar, }, gpgdir: { type: 'String', desc: 'Path to store the GPG key.', default: '/root', behaviour: :namevar, }, }, ) ``` ``` class Puppet::Provider::Gpgkey::Gpgkey < Puppet::ResourceApi::SimpleProvider def get(context, name = []) context.debug('Returning pre-canned example data for: %s' % name.inspect) [ { title: '/root/foo', name: 'foo', gpgdir: '/root', ensure: 'present', }, #{ # title: '/root/bar', # name: 'bar', # gpgdir: '/root', # ensure: 'present', #}, ] end def create(context, name, should) context.notice("Creating '#{name}' with #{should.inspect}") end def update(context, name, should) context.notice("Updating '#{name}' with #{should.inspect}") end def delete(context, name) context.notice("Deleting '#{name}'") end end ``` ``` gpgkey { 'baz1': ensure => present, name => 'foo', gpgdir => '/root'; '/root/bar': ensure => present; '/root/foo2': ensure => present; } ``` ``` Info: Applying configuration version '1558363097' Debug: gpgkey supports `simple_get_filter` Debug: gpgkey: Returning pre-canned example data for: ["foo"] Debug: gpgkey does not support `canonicalize` Debug: Current State: {:title=>"/root/foo", :name=>"foo", :gpgdir=>"/root", :ensure=>"present"} Debug: gpgkey supports `simple_get_filter` Debug: gpgkey: Returning pre-canned example data for: ["bar"] Debug: Current State: {:title=>"bar", :ensure=>:absent} Notice: /Stage[main]/Main/Gpgkey[bar]/ensure: defined 'ensure' as 'present' Debug: gpgkey does not support `canonicalize` Debug: Target State: {:name=>"bar", :ensure=>"present", :gpgdir=>"/root"} Debug: gpgkey does not support `supports_noop` Debug: gpgkey supports `simple_get_filter` Debug: gpgkey[bar]: Creating: Start Notice: gpgkey[bar]: Creating: Creating 'bar' with {:name=>"bar", :ensure=>"present", :gpgdir=>"/root"} Notice: gpgkey[bar]: Creating: Finished in 0.000085 seconds Debug: /Stage[main]/Main/Gpgkey[bar]: The container Class[Main] will propagate my refresh event Debug: gpgkey supports `simple_get_filter` Debug: gpgkey: Returning pre-canned example data for: ["foo2"] Debug: Current State: {:title=>"foo2", :ensure=>:absent} Notice: /Stage[main]/Main/Gpgkey[foo2]/ensure: defined 'ensure' as 'present' Debug: gpgkey does not support `canonicalize` Debug: Target State: {:name=>"foo2", :ensure=>"present", :gpgdir=>"/root"} Debug: gpgkey does not support `supports_noop` Debug: gpgkey supports `simple_get_filter` Debug: gpgkey[foo2]: Creating: Start Notice: gpgkey[foo2]: Creating: Creating 'foo2' with {:name=>"foo2", :ensure=>"present", :gpgdir=>"/root"} Notice: gpgkey[foo2]: Creating: Finished in 0.000069 seconds Debug: /Stage[main]/Main/Gpgkey[foo2]: The container Class[Main] will propagate my refresh event Debug: Class[Main]: The container Stage[main] will propagate my refresh event Debug: Finishing transaction 47323787575300 Debug: Storing state Debug: Pruned old state cache entries in 0.00 seconds Debug: Stored state in 0.01 seconds Notice: Applied catalog in 0.03 seconds ``` As can be seen in the `Returning pre-canned example data for` messages, only `name`, but not `gpgdir` is passed through. This is because of the weakness of title generation in https://github.com/puppetlabs/puppet-resource_api/blob/d249941cf7544005ad66b9bb54e079ffdfc0ac45/lib/puppet/resource_api.rb#L230-L235 After these changes, a hash of namevars and their values is used as a title when requesting resources from the provider: ``` Info: Applying configuration version '1561397939' Debug: gpgkey: Returning pre-canned example data for: [{:name=>"foo", :gpgdir=>"/root"}] Debug: Current State: {:title=>"/root/foo", :name=>"foo", :gpgdir=>"/root", :ensure=>"present"} Debug: gpgkey: Returning pre-canned example data for: [{:name=>"bar", :gpgdir=>"/root"}] Debug: Current State: {:name=>"bar", :gpgdir=>"/root", :ensure=>:absent} Notice: /Stage[main]/Main/Gpgkey[bar]/ensure: defined 'ensure' as 'present' Debug: Target State: {:name=>"bar", :gpgdir=>"/root", :ensure=>"present"} Debug: gpgkey[{:name=>"bar", :gpgdir=>"/root"}]: Creating: Start Notice: gpgkey[{:name=>"bar", :gpgdir=>"/root"}]: Creating: Creating '{:title=>{:name=>"bar", :gpgdir=>"/root"}, :name=>"bar", :gpgdir=>"/root"}' with {:name=>"bar", :gpgdir=>"/root", :ensure=>"present"} Notice: gpgkey[{:name=>"bar", :gpgdir=>"/root"}]: Creating: Finished in 0.000091 seconds Debug: /Stage[main]/Main/Gpgkey[bar]: The container Class[Main] will propagate my refresh event Debug: gpgkey: Returning pre-canned example data for: [{:name=>"foo2", :gpgdir=>"/root"}] Debug: Current State: {:name=>"foo2", :gpgdir=>"/root", :ensure=>:absent} Notice: /Stage[main]/Main/Gpgkey[foo2]/ensure: defined 'ensure' as 'present' Debug: Target State: {:name=>"foo2", :gpgdir=>"/root", :ensure=>"present"} Debug: gpgkey[{:name=>"foo2", :gpgdir=>"/root"}]: Creating: Start Notice: gpgkey[{:name=>"foo2", :gpgdir=>"/root"}]: Creating: Creating '{:title=>{:name=>"foo2", :gpgdir=>"/root"}, :name=>"foo2", :gpgdir=>"/root"}' with {:name=>"foo2", :gpgdir=>"/root", :ensure=>"present"} Notice: gpgkey[{:name=>"foo2", :gpgdir=>"/root"}]: Creating: Finished in 0.000116 seconds Debug: /Stage[main]/Main/Gpgkey[foo2]: The container Class[Main] will propagate my refresh event Debug: Class[Main]: The container Stage[main] will propagate my refresh event Debug: Finishing transaction 47326046031800 Debug: Storing state Debug: Pruned old state cache entries in 0.00 seconds Debug: Stored state in 0.01 seconds Notice: Applied catalog in 0.02 seconds ``` The provider should return a properly formatted `title` value from `get` to enable pretty formatting in logs and `puppet resource` output. # Conflicts: # spec/acceptance/composite_namevar_spec.rb
1 parent 3f52b58 commit 7ab1d9e

File tree

10 files changed

+146
-46
lines changed

10 files changed

+146
-46
lines changed

Rakefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ RSpec::Core::RakeTask.new(:spec) do |t|
1919
if RUBY_PLATFORM == 'java'
2020
excludes += ['acceptance/**/*.rb', 'integration/**/*.rb', 'puppet/resource_api/*_context_spec.rb', 'puppet/util/network_device/simple/device_spec.rb']
2121
t.rspec_opts = '--tag ~agent_test'
22+
t.rspec_opts << ' --tag ~j17_exclude' if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0.0')
2223
end
2324
t.exclude_pattern = "spec/{#{excludes.join ','}}"
2425
end

lib/puppet/resource_api.rb

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,20 @@ def name
133133
title
134134
end
135135

136+
def self.build_title(type_definition, resource_hash)
137+
if type_definition.namevars.size > 1
138+
# use a MonkeyHash to allow searching in Puppet's RAL
139+
Puppet::ResourceApi::MonkeyHash[type_definition.namevars.map { |attr| [attr, resource_hash[attr]] }]
140+
else
141+
resource_hash[type_definition.namevars[0]]
142+
end
143+
end
144+
145+
def rsapi_title
146+
@rsapi_title ||= self.class.build_title(type_definition, self)
147+
@rsapi_title
148+
end
149+
136150
def to_resource
137151
to_resource_shim(super)
138152
end
@@ -261,7 +275,7 @@ def self.instances
261275
result = if resource_hash.key? :title
262276
new(title: resource_hash[:title])
263277
else
264-
new(title: resource_hash[type_definition.namevars.first])
278+
new(title: build_title(type_definition, resource_hash))
265279
end
266280
result.cache_current_state(resource_hash)
267281
result
@@ -270,7 +284,7 @@ def self.instances
270284

271285
def refresh_current_state
272286
@rsapi_current_state = if type_definition.feature?('simple_get_filter')
273-
my_provider.get(context, [title]).find { |h| namevar_match?(h) }
287+
my_provider.get(context, [rsapi_title]).find { |h| namevar_match?(h) }
274288
else
275289
my_provider.get(context).find { |h| namevar_match?(h) }
276290
end
@@ -279,7 +293,11 @@ def refresh_current_state
279293
type_definition.check_schema(@rsapi_current_state)
280294
strict_check(@rsapi_current_state) if type_definition.feature?('canonicalize')
281295
else
282-
@rsapi_current_state = { title: title }
296+
@rsapi_current_state = if rsapi_title.is_a? Hash
297+
rsapi_title.dup
298+
else
299+
{ title: rsapi_title }
300+
end
283301
@rsapi_current_state[:ensure] = :absent if type_definition.ensurable?
284302
end
285303
end
@@ -340,9 +358,9 @@ def flush
340358
end
341359

342360
if type_definition.feature?('supports_noop')
343-
my_provider.set(context, { title => { is: @rsapi_current_state, should: target_state } }, noop: noop?)
361+
my_provider.set(context, { rsapi_title => { is: @rsapi_current_state, should: target_state } }, noop: noop?)
344362
else
345-
my_provider.set(context, title => { is: @rsapi_current_state, should: target_state }) unless noop?
363+
my_provider.set(context, rsapi_title => { is: @rsapi_current_state, should: target_state }) unless noop?
346364
end
347365
raise 'Execution encountered an error' if context.failed?
348366

lib/puppet/resource_api/glue.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,19 @@ def filtered_keys
5757
values.keys.reject { |k| k == :title || !attr_def[k] || (attr_def[k][:behaviour] == :namevar && @namevars.size == 1) }
5858
end
5959
end
60+
61+
# this hash allows key-value based ordering comparisons between instances of this and instances of this and other classes
62+
# this is required for `lib/puppet/indirector/resource/ral.rb`'s `search` method which expects all titles to be comparable
63+
class MonkeyHash < Hash
64+
def <=>(other)
65+
result = self.class.name <=> other.class.name
66+
if result.zero?
67+
result = keys.sort <=> other.keys.sort
68+
end
69+
if result.zero?
70+
result = keys.sort.map { |k| self[k] } <=> other.keys.sort.map { |k| other[k] }
71+
end
72+
result
73+
end
74+
end
6075
end

spec/acceptance/composite_namevar_spec.rb

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@
3131
stdout_str, status = Open3.capture2e("puppet resource #{common_args} composite_namevar php/gem")
3232
expect(stdout_str.strip).to match %r{^composite_namevar \{ \'php/gem\'}
3333
expect(stdout_str.strip).to match %r{ensure\s*=> \'present\'}
34-
expect(stdout_str.strip).to match %r{Looking for \["php/gem"\]}
34+
expect(stdout_str.strip).to match %r{Looking for \[\{:package=>"php", :manager=>"gem"\}\]}
3535
expect(status.exitstatus).to eq 0
3636
end
3737
it 'properly identifies an absent resource if only the title is provided' do
3838
stdout_str, status = Open3.capture2e("puppet resource #{common_args} composite_namevar php-wibble")
3939
expect(stdout_str.strip).to match %r{^composite_namevar \{ \'php-wibble\'}
4040
expect(stdout_str.strip).to match %r{ensure\s*=> \'absent\'}
41-
expect(stdout_str.strip).to match %r{Looking for \["php-wibble"\]}
41+
expect(stdout_str.strip).to match %r{Looking for \[\{:package=>"php", :manager=>"wibble"\}\]}
4242
expect(status.exitstatus).to eq 0
4343
end
4444
it 'creates a previously absent resource' do
@@ -47,7 +47,7 @@
4747
expect(stdout_str.strip).to match %r{ensure\s*=> \'present\'}
4848
expect(stdout_str.strip).to match %r{package\s*=> \'php\'}
4949
expect(stdout_str.strip).to match %r{manager\s*=> \'wibble\'}
50-
expect(stdout_str.strip).to match %r{Looking for \["php-wibble"\]}
50+
expect(stdout_str.strip).to match %r{Looking for \[\{:package=>"php", :manager=>"wibble"\}\]}
5151
expect(status.exitstatus).to eq 0
5252
end
5353
it 'will remove an existing resource' do
@@ -56,7 +56,7 @@
5656
expect(stdout_str.strip).to match %r{package\s*=> \'php\'}
5757
expect(stdout_str.strip).to match %r{manager\s*=> \'gem\'}
5858
expect(stdout_str.strip).to match %r{ensure\s*=> \'absent\'}
59-
expect(stdout_str.strip).to match %r{Looking for \["php-gem"\]}
59+
expect(stdout_str.strip).to match %r{Looking for \[\{:package=>"php", :manager=>"gem"\}\]}
6060
expect(status.exitstatus).to eq 0
6161
end
6262
end
@@ -79,31 +79,31 @@
7979
let(:manifest) { 'composite_namevar { php-gem: }' }
8080

8181
it { expect(@stdout_str).to match %r{Current State: \{:title=>"php-gem", :package=>"php", :manager=>"gem", :ensure=>"present", :value=>"b"\}} }
82-
it { expect(@stdout_str).to match %r{Looking for \["php-gem"\]} }
82+
it { expect(@stdout_str).to match %r{Looking for \[\{:package=>"php", :manager=>"gem"\}\]} }
8383
it { expect(@status.exitstatus).to eq 0 }
8484
end
8585

8686
context 'when managing an absent instance' do
8787
let(:manifest) { 'composite_namevar { php-wibble: ensure=>\'absent\' }' }
8888

8989
it { expect(@stdout_str).to match %r{Composite_namevar\[php-wibble\]: Nothing to manage: no ensure and the resource doesn't exist} }
90-
it { expect(@stdout_str).to match %r{Looking for \["php-wibble"\]} }
90+
it { expect(@stdout_str).to match %r{Looking for \[\{:package=>"php", :manager=>"wibble"\}\]} }
9191
it { expect(@status.exitstatus).to eq 0 }
9292
end
9393

9494
context 'when creating a previously absent instance' do
9595
let(:manifest) { 'composite_namevar { php-wibble: ensure=>\'present\' }' }
9696

9797
it { expect(@stdout_str).to match %r{Composite_namevar\[php-wibble\]/ensure: defined 'ensure' as 'present'} }
98-
it { expect(@stdout_str).to match %r{Looking for \["php-wibble"\]} }
98+
it { expect(@stdout_str).to match %r{Looking for \[\{:package=>"php", :manager=>"wibble"\}\]} }
9999
it { expect(@status.exitstatus).to eq 2 }
100100
end
101101

102102
context 'when removing a previously present instance' do
103103
let(:manifest) { 'composite_namevar { php-yum: ensure=>\'absent\' }' }
104104

105105
it { expect(@stdout_str).to match %r{Composite_namevar\[php-yum\]/ensure: undefined 'ensure' from 'present'} }
106-
it { expect(@stdout_str).to match %r{Looking for \["php-yum"\]} }
106+
it { expect(@stdout_str).to match %r{Looking for \[\{:package=>"php", :manager=>"yum"\}\]} }
107107
it { expect(@status.exitstatus).to eq 2 }
108108
end
109109

@@ -112,7 +112,7 @@
112112

113113
it { expect(@stdout_str).to match %r{Current State: \{:title=>"php-gem", :package=>"php", :manager=>"gem", :ensure=>"present", :value=>"b"\}} }
114114
it { expect(@stdout_str).to match %r{Target State: \{:package=>"php", :manager=>"gem", :value=>"c", :ensure=>"present"\}} }
115-
it { expect(@stdout_str).to match %r{Looking for \["php/gem"\]} }
115+
it { expect(@stdout_str).to match %r{Looking for \[\{:package=>"php", :manager=>"gem"\}\]} }
116116
it { expect(@status.exitstatus).to eq 2 }
117117
end
118118
end
@@ -122,31 +122,31 @@
122122
let(:manifest) { 'composite_namevar { "sometitle": package => "php", manager => "gem" }' }
123123

124124
it { expect(@stdout_str).to match %r{Current State: \{:title=>"php-gem", :package=>"php", :manager=>"gem", :ensure=>"present", :value=>"b"\}} }
125-
it { expect(@stdout_str).to match %r{Looking for \["sometitle"\]} }
125+
it { expect(@stdout_str).to match %r{Looking for \[\{:package=>"php", :manager=>"gem"\}\]} }
126126
it { expect(@status.exitstatus).to eq 0 }
127127
end
128128

129129
context 'when managing an absent instance' do
130130
let(:manifest) { 'composite_namevar { "sometitle": ensure => "absent", package => "php", manager => "wibble" }' }
131131

132132
it { expect(@stdout_str).to match %r{Composite_namevar\[sometitle\]: Nothing to manage: no ensure and the resource doesn't exist} }
133-
it { expect(@stdout_str).to match %r{Looking for \["sometitle"\]} }
133+
it { expect(@stdout_str).to match %r{Looking for \[\{:package=>"php", :manager=>"wibble"\}\]} }
134134
it { expect(@status.exitstatus).to eq 0 }
135135
end
136136

137137
context 'when creating a previously absent instance' do
138138
let(:manifest) { 'composite_namevar { "sometitle": ensure => "present", package => "php", manager => "wibble" }' }
139139

140140
it { expect(@stdout_str).to match %r{Composite_namevar\[sometitle\]/ensure: defined 'ensure' as 'present'} }
141-
it { expect(@stdout_str).to match %r{Looking for \["sometitle"\]} }
141+
it { expect(@stdout_str).to match %r{Looking for \[\{:package=>"php", :manager=>"wibble"\}\]} }
142142
it { expect(@status.exitstatus).to eq 2 }
143143
end
144144

145145
context 'when removing a previously present instance' do
146146
let(:manifest) { 'composite_namevar { "sometitle": ensure => "absent", package => "php", manager => "yum" }' }
147147

148148
it { expect(@stdout_str).to match %r{Composite_namevar\[sometitle\]/ensure: undefined 'ensure' from 'present'} }
149-
it { expect(@stdout_str).to match %r{Looking for \["sometitle"\]} }
149+
it { expect(@stdout_str).to match %r{Looking for \[\{:package=>"php", :manager=>"yum"\}\]} }
150150
it { expect(@status.exitstatus).to eq 2 }
151151
end
152152
end

spec/acceptance/namevar_spec.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@
2424
expect(stdout_str.strip).to match %r{ensure\s*=> \'present\'}
2525
expect(status).to eq 0
2626
end
27-
it 'returns the match if title matches a namevar value' do
28-
stdout_str, status = Open3.capture2e("puppet resource #{common_args} multiple_namevar php")
29-
expect(stdout_str.strip).to match %r{^multiple_namevar \{ \'php\'}
27+
it 'returns the match if title matches a title value' do
28+
stdout_str, status = Open3.capture2e("puppet resource #{common_args} multiple_namevar php-gem")
29+
expect(stdout_str.strip).to match %r{^multiple_namevar \{ \'php-gem\'}
3030
expect(stdout_str.strip).to match %r{ensure\s*=> \'present\'}
3131
expect(stdout_str.strip).to match %r{package\s*=> \'php\'}
32+
expect(stdout_str.strip).to match %r{manager\s*=> \'gem\'}
3233
expect(status).to eq 0
3334
end
3435
it 'creates a previously absent resource if all namevars are provided' do

spec/fixtures/test_module/lib/puppet/provider/composite_namevar/composite_namevar.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
require 'puppet/resource_api'
22
require 'puppet/resource_api/simple_provider'
33

4-
# Implementation for the title_provider type using the Resource API.
4+
# Implementation for the composite_namevar type using the Resource API.
55
class Puppet::Provider::CompositeNamevar::CompositeNamevar < Puppet::ResourceApi::SimpleProvider
66
def initialize
77
@current_values ||= [

spec/fixtures/test_module/lib/puppet/provider/multiple_namevar/multiple_namevar.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
class Puppet::Provider::MultipleNamevar::MultipleNamevar
55
def initialize
66
@current_values ||= [
7-
{ package: 'php', manager: 'yum', ensure: 'present' },
8-
{ package: 'php', manager: 'gem', ensure: 'present' },
9-
{ package: 'mysql', manager: 'yum', ensure: 'present' },
10-
{ package: 'mysql', manager: 'gem', ensure: 'present' },
11-
{ package: 'foo', manager: 'bar', ensure: 'present' },
12-
{ package: 'bar', manager: 'foo', ensure: 'present' },
7+
{ title: 'php-yum', package: 'php', manager: 'yum', ensure: 'present' },
8+
{ title: 'php-gem', package: 'php', manager: 'gem', ensure: 'present' },
9+
{ title: 'mysql-yum', package: 'mysql', manager: 'yum', ensure: 'present' },
10+
{ title: 'mysql-gem', package: 'mysql', manager: 'gem', ensure: 'present' },
11+
{ title: 'foo-bar', package: 'foo', manager: 'bar', ensure: 'present' },
12+
{ title: 'bar-foo', package: 'bar', manager: 'foo', ensure: 'present' },
1313
]
1414
end
1515

spec/integration/resource_api_spec.rb

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,27 @@
77
let(:definition) do
88
{
99
name: 'integration',
10+
title_patterns: [
11+
{
12+
pattern: %r{^(?<name>.*[^-])-(?<name2>.*)$},
13+
desc: 'Where the name and the name2 are provided with a hyphen separator',
14+
},
15+
{
16+
pattern: %r{^(?<name>.*)$},
17+
desc: 'Where only the name is provided',
18+
},
19+
],
1020
attributes: {
1121
name: {
1222
type: 'String',
1323
behaviour: :namevar,
1424
desc: 'the title',
1525
},
26+
name2: {
27+
type: 'String',
28+
behaviour: :namevar,
29+
desc: 'the other title',
30+
},
1631
string: {
1732
type: 'String',
1833
desc: 'a string attribute',
@@ -170,7 +185,18 @@
170185
s = setter
171186
Class.new do
172187
def get(_context)
173-
[]
188+
[
189+
{
190+
name: 'foo',
191+
name2: 'bar',
192+
title: 'foo-bar',
193+
},
194+
{
195+
name: 'foo2',
196+
name2: 'bar2',
197+
title: 'foo2-bar2',
198+
},
199+
]
174200
end
175201

176202
attr_reader :last_changes
@@ -198,7 +224,7 @@ def get(_context)
198224
# See spec/acceptance/metaparam_spec.rb for more in-depth testing with a full puppet apply
199225
let(:catalog) { instance_double('Puppet::Resource::Catalog', 'catalog') }
200226
let(:instance) do
201-
type.new(name: 'somename', ensure: 'present', boolean: true, integer: 15, float: 1.23,
227+
type.new(name: 'somename', name2: 'othername', ensure: 'present', boolean: true, integer: 15, float: 1.23,
202228
variant_pattern: '0x1234ABCD', url: 'http://www.google.com', sensitive: Puppet::Pops::Types::PSensitiveType::Sensitive.new('a password'),
203229
string_array: %w[a b c],
204230
variant_array: 'not_an_array', array_of_arrays: [%w[a b c], %w[d e f]],
@@ -225,7 +251,7 @@ def get(_context)
225251
end
226252

227253
it 'can serialize to json' do
228-
expect({ 'resources' => [instance.to_resource] }.to_json).to eq '{"resources":[{"somename":{"ensure":"absent","boolean_param":false,"integer_param":99,"float_param":3.21,"ensure_param":"present","variant_pattern_param":"1234ABCD","url_param":"http://www.puppet.com","string_array_param":"d","e":"f","string_param":"default value"}}]}' # rubocop:disable Metrics/LineLength
254+
expect({ 'resources' => [instance.to_resource] }.to_json).to eq '{"resources":[{"somename":{"name":"somename","name2":"othername","ensure":"absent","boolean_param":false,"integer_param":99,"float_param":3.21,"ensure_param":"present","variant_pattern_param":"1234ABCD","url_param":"http://www.puppet.com","string_array_param":"d","e":"f","string_param":"default value"}}]}' # rubocop:disable Metrics/LineLength
229255
end
230256
end
231257

spec/puppet/resource_api/glue_spec.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,20 @@
7878
it { expect(instance.to_hash).to eq(namevarname: 'title', attr: 'value', attr_ro: 'fixed') }
7979
end
8080
end
81+
82+
describe Puppet::ResourceApi::MonkeyHash do
83+
it { expect(described_class.ancestors).to include Hash }
84+
85+
describe '#<=>(other)' do
86+
subject(:value) { described_class[b: 'b', c: 'c'] }
87+
88+
it { expect(value <=> 'string').to eq(-1) }
89+
# Avoid this test on jruby 1.7, where it is hitting a implementation inconsistency and `'string' <=> value` returns `nil`
90+
it('compares to a string', j17_exclude: true) { expect('string' <=> value).to eq 1 }
91+
it { expect(value <=> described_class[b: 'b', c: 'c']).to eq 0 }
92+
it { expect(value <=> described_class[d: 'd']).to eq(-1) }
93+
it { expect(value <=> described_class[a: 'a']).to eq 1 }
94+
it { expect(value <=> described_class[b: 'a', c: 'c']).to eq 1 }
95+
end
96+
end
8197
end

0 commit comments

Comments
 (0)