Skip to content

Commit 3f52b58

Browse files
committed
(MODULES-9428) show how simple_get_filter+composite namevars is broken
This change adds acceptance tests showing how enabling `simple_get_filter` for a type with composite namevars will break when a user sets a custom title for a resource and uses attributes to pass in the namevar values instead: ``` let(:manifest) { 'composite_namevar { "sometitle": ensure => "present", package => "php", manager => "wibble" }' } it { expect(@stdout_str).to match %r{Looking for \["sometitle"\]} } ``` This behaviour is misleading at best (as authors might expect `name` to always match all namevars through a title pattern) and completely debilitating at worst, when a custom title is passed to `delete` and there is no indication which resource to delete.
1 parent d75a134 commit 3f52b58

File tree

3 files changed

+86
-33
lines changed

3 files changed

+86
-33
lines changed
Lines changed: 79 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
require 'spec_helper'
21
require 'open3'
2+
require 'spec_helper'
3+
require 'tempfile'
34

45
RSpec.describe 'a type with composite namevars' do
56
let(:common_args) { '--verbose --trace --debug --strict=error --modulepath spec/fixtures' }
@@ -8,6 +9,7 @@
89
it 'is returns the values correctly' do
910
stdout_str, status = Open3.capture2e("puppet resource #{common_args} composite_namevar")
1011
expect(stdout_str.strip).to match %r{^composite_namevar}
12+
expect(stdout_str.strip).to match %r{Looking for \[\]}
1113
expect(status).to eq 0
1214
end
1315
it 'returns the required resource correctly' do
@@ -16,23 +18,27 @@
1618
expect(stdout_str.strip).to match %r{ensure\s*=> \'present\'}
1719
expect(stdout_str.strip).to match %r{package\s*=> \'php\'}
1820
expect(stdout_str.strip).to match %r{manager\s*=> \'yum\'}
21+
expect(stdout_str.strip).to match %r{Looking for \[\]}
1922
expect(status.exitstatus).to eq 0
2023
end
21-
it 'Throws error if title is not a matching title_pattern' do
22-
stdout_str, status = Open3.capture2e("puppet resource #{common_args} composite_namevar php package=php manager=yum")
23-
expect(stdout_str.strip).to match %r{No set of title patterns matched the title "php"}
24+
it 'throws error if title is not a matching title_pattern' do
25+
stdout_str, status = Open3.capture2e("puppet resource #{common_args} composite_namevar php123 package=php manager=yum")
26+
expect(stdout_str.strip).to match %r{No set of title patterns matched the title "php123"}
27+
expect(stdout_str.strip).not_to match %r{Looking for}
2428
expect(status.exitstatus).to eq 1
2529
end
2630
it 'returns the match if alternative title_pattern matches' do
2731
stdout_str, status = Open3.capture2e("puppet resource #{common_args} composite_namevar php/gem")
2832
expect(stdout_str.strip).to match %r{^composite_namevar \{ \'php/gem\'}
2933
expect(stdout_str.strip).to match %r{ensure\s*=> \'present\'}
34+
expect(stdout_str.strip).to match %r{Looking for \["php/gem"\]}
3035
expect(status.exitstatus).to eq 0
3136
end
3237
it 'properly identifies an absent resource if only the title is provided' do
3338
stdout_str, status = Open3.capture2e("puppet resource #{common_args} composite_namevar php-wibble")
3439
expect(stdout_str.strip).to match %r{^composite_namevar \{ \'php-wibble\'}
3540
expect(stdout_str.strip).to match %r{ensure\s*=> \'absent\'}
41+
expect(stdout_str.strip).to match %r{Looking for \["php-wibble"\]}
3642
expect(status.exitstatus).to eq 0
3743
end
3844
it 'creates a previously absent resource' do
@@ -41,6 +47,7 @@
4147
expect(stdout_str.strip).to match %r{ensure\s*=> \'present\'}
4248
expect(stdout_str.strip).to match %r{package\s*=> \'php\'}
4349
expect(stdout_str.strip).to match %r{manager\s*=> \'wibble\'}
50+
expect(stdout_str.strip).to match %r{Looking for \["php-wibble"\]}
4451
expect(status.exitstatus).to eq 0
4552
end
4653
it 'will remove an existing resource' do
@@ -49,16 +56,16 @@
4956
expect(stdout_str.strip).to match %r{package\s*=> \'php\'}
5057
expect(stdout_str.strip).to match %r{manager\s*=> \'gem\'}
5158
expect(stdout_str.strip).to match %r{ensure\s*=> \'absent\'}
59+
expect(stdout_str.strip).to match %r{Looking for \["php-gem"\]}
5260
expect(status.exitstatus).to eq 0
5361
end
5462
end
5563

5664
describe 'using `puppet apply`' do
57-
require 'tempfile'
58-
5965
let(:common_args) { super() + ' --detailed-exitcodes' }
6066

61-
# run Open3.capture2e only once to get both output, and exitcode # rubocop:disable RSpec/InstanceVariable
67+
# run Open3.capture2e only once to get both output, and exitcode
68+
# rubocop:disable RSpec/InstanceVariable
6269
before(:each) do
6370
Tempfile.create('acceptance') do |f|
6471
f.write(manifest)
@@ -67,42 +74,82 @@
6774
end
6875
end
6976

70-
context 'when managing a present instance' do
71-
let(:manifest) { 'composite_namevar { php-gem: }' }
77+
context 'when matching title patterns' do
78+
context 'when managing a present instance' do
79+
let(:manifest) { 'composite_namevar { php-gem: }' }
7280

73-
it { expect(@stdout_str).to match %r{Current State: \{:title=>"php-gem", :package=>"php", :manager=>"gem", :ensure=>"present", :value=>"b"\}} }
74-
it { expect(@status.exitstatus).to eq 0 }
75-
end
81+
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"\]} }
83+
it { expect(@status.exitstatus).to eq 0 }
84+
end
7685

77-
context 'when managing an absent instance' do
78-
let(:manifest) { 'composite_namevar { php-wibble: ensure=>\'absent\' }' }
86+
context 'when managing an absent instance' do
87+
let(:manifest) { 'composite_namevar { php-wibble: ensure=>\'absent\' }' }
7988

80-
it { expect(@stdout_str).to match %r{Composite_namevar\[php-wibble\]: Nothing to manage: no ensure and the resource doesn't exist} }
81-
it { expect(@status.exitstatus).to eq 0 }
82-
end
89+
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"\]} }
91+
it { expect(@status.exitstatus).to eq 0 }
92+
end
8393

84-
context 'when creating a previously absent instance' do
85-
let(:manifest) { 'composite_namevar { php-wibble: ensure=>\'present\' }' }
94+
context 'when creating a previously absent instance' do
95+
let(:manifest) { 'composite_namevar { php-wibble: ensure=>\'present\' }' }
8696

87-
it { expect(@stdout_str).to match %r{Composite_namevar\[php-wibble\]/ensure: defined 'ensure' as 'present'} }
88-
it { expect(@status.exitstatus).to eq 2 }
89-
end
97+
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"\]} }
99+
it { expect(@status.exitstatus).to eq 2 }
100+
end
90101

91-
context 'when removing a previously present instance' do
92-
let(:manifest) { 'composite_namevar { php-yum: ensure=>\'absent\' }' }
102+
context 'when removing a previously present instance' do
103+
let(:manifest) { 'composite_namevar { php-yum: ensure=>\'absent\' }' }
93104

94-
it { expect(@stdout_str).to match %r{Composite_namevar\[php-yum\]/ensure: undefined 'ensure' from 'present'} }
95-
it { expect(@status.exitstatus).to eq 2 }
96-
end
105+
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"\]} }
107+
it { expect(@status.exitstatus).to eq 2 }
108+
end
97109

98-
context 'when modifying an existing resource through an alternative title_pattern' do
99-
let(:manifest) { 'composite_namevar { \'php/gem\': value=>\'c\' }' }
110+
context 'when modifying an existing resource through an alternative title_pattern' do
111+
let(:manifest) { 'composite_namevar { \'php/gem\': value=>\'c\' }' }
100112

101-
it { expect(@stdout_str).to match %r{Current State: \{:title=>"php-gem", :package=>"php", :manager=>"gem", :ensure=>"present", :value=>"b"\}} }
102-
it { expect(@stdout_str).to match %r{Target State: \{:package=>"php", :manager=>"gem", :value=>"c", :ensure=>"present"\}} }
103-
it { expect(@status.exitstatus).to eq 2 }
113+
it { expect(@stdout_str).to match %r{Current State: \{:title=>"php-gem", :package=>"php", :manager=>"gem", :ensure=>"present", :value=>"b"\}} }
114+
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"\]} }
116+
it { expect(@status.exitstatus).to eq 2 }
117+
end
104118
end
105119

120+
context 'when using attributes' do
121+
context 'when managing a present instance' do
122+
let(:manifest) { 'composite_namevar { "sometitle": package => "php", manager => "gem" }' }
123+
124+
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"\]} }
126+
it { expect(@status.exitstatus).to eq 0 }
127+
end
128+
129+
context 'when managing an absent instance' do
130+
let(:manifest) { 'composite_namevar { "sometitle": ensure => "absent", package => "php", manager => "wibble" }' }
131+
132+
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"\]} }
134+
it { expect(@status.exitstatus).to eq 0 }
135+
end
136+
137+
context 'when creating a previously absent instance' do
138+
let(:manifest) { 'composite_namevar { "sometitle": ensure => "present", package => "php", manager => "wibble" }' }
139+
140+
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"\]} }
142+
it { expect(@status.exitstatus).to eq 2 }
143+
end
144+
145+
context 'when removing a previously present instance' do
146+
let(:manifest) { 'composite_namevar { "sometitle": ensure => "absent", package => "php", manager => "yum" }' }
147+
148+
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"\]} }
150+
it { expect(@status.exitstatus).to eq 2 }
151+
end
152+
end
106153
# rubocop:enable RSpec/InstanceVariable
107154
end
108155
end

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ def initialize
1414
]
1515
end
1616

17-
def get(_context)
17+
def get(context, names = nil)
18+
context.notice("Looking for #{names.inspect}")
1819
@current_values
1920
end
2021

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
docs: <<-DOC,
66
This type provides Puppet with the capabilities to manage ...
77
DOC
8+
features: [ 'simple_get_filter' ],
89
title_patterns: [
910
{
1011
pattern: %r{^(?<package>.*[^-])-(?<manager>.*)$},
@@ -14,6 +15,10 @@
1415
pattern: %r{^(?<package>.*[^/])/(?<manager>.*)$},
1516
desc: 'Where the package and the manager are provided with a forward slash separator',
1617
},
18+
{
19+
pattern: %r{^(?<package>[a-z]*[^/])$},
20+
desc: 'Fallback pattern where only the package is provided',
21+
},
1722
],
1823
attributes: {
1924
ensure: {

0 commit comments

Comments
 (0)