puppet-lint 2.1.1 → 2.2.0

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.
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'arrow_on_right_operand_line' do
4
+ {'chain' => '->', 'subscribe chain' => '~>'}.each do |name, operator|
5
+ context "#{name} operator" do
6
+ context 'both operands on same line' do
7
+ let(:code) { "Package['httpd'] #{operator} Service['httpd']" }
8
+
9
+ it { expect(problems).to have(0).problems }
10
+ end
11
+
12
+ context 'arrow on the line of left operand' do
13
+ let(:code) do
14
+ "Package['httpd'] #{operator}
15
+ Service['httpd']"
16
+ end
17
+
18
+ it { expect(problems).to have(1).problems }
19
+
20
+ context 'with fix enabled' do
21
+ before do
22
+ PuppetLint.configuration.fix = true
23
+ end
24
+
25
+ after do
26
+ PuppetLint.configuration.fix = false
27
+ end
28
+
29
+ let(:fixed) do
30
+ "Package['httpd']
31
+ #{operator} Service['httpd']"
32
+ end
33
+
34
+ it { expect(manifest).to eq (fixed) }
35
+ end
36
+ end
37
+
38
+ context 'arrow on the line of right operand' do
39
+ let(:code) { "Package['httpd']
40
+ #{operator} Service['httpd']" }
41
+
42
+ it { expect(problems).to have(0).problems }
43
+ end
44
+ end
45
+ end
46
+ end
@@ -169,6 +169,37 @@ describe 'variable_scope' do
169
169
  end
170
170
  end
171
171
 
172
+ context 'nested future parser blocks' do
173
+ let(:code) { "
174
+ class foo() {
175
+ $foo = {1=>2, 3=>4}
176
+ $bar = [1, 2, 3]
177
+ $foo.each |$k ,$v| {
178
+ $k
179
+ $v
180
+ $x # top-scope warning
181
+ $bar.each |$x| {
182
+ $k
183
+ $v
184
+ $x
185
+ $p # top-scope warning
186
+ }
187
+ $x # top-scope warning
188
+ }
189
+ }
190
+ " }
191
+
192
+ it 'should only detect three problems' do
193
+ expect(problems).to have(3).problem
194
+ end
195
+
196
+ it 'should create three warnings' do
197
+ expect(problems).to contain_warning(msg).on_line(8).in_column(11)
198
+ expect(problems).to contain_warning(msg).on_line(13).in_column(13)
199
+ expect(problems).to contain_warning(msg).on_line(15).in_column(11)
200
+ end
201
+ end
202
+
172
203
  %w{alias audit before loglevel noop notify require schedule stage subscribe tag}.each do |metaparam|
173
204
  context "referencing #{metaparam} metaparam value as a variable" do
174
205
  let(:code) { "
@@ -208,4 +239,46 @@ describe 'variable_scope' do
208
239
  expect(problems).to have(0).problems
209
240
  end
210
241
  end
242
+
243
+ context 'nested variable assignment' do
244
+ let(:code) { "
245
+ class test {
246
+ [$foo, [[$bar, $baz], $qux]] = something()
247
+ }
248
+ " }
249
+
250
+ it 'should not detect any problems' do
251
+ expect(problems).to have(0).problems
252
+ end
253
+ end
254
+
255
+ context 'function calls inside string interpolation' do
256
+ let(:code) { "
257
+ class test {
258
+ \"${split('1,2,3', ',')}\" # split is a function
259
+ \"${lookup('foo::bar')}\" # lookup is a function
260
+ }
261
+ " }
262
+
263
+ it 'should not detect any problems' do
264
+ expect(problems).to have(0).problems
265
+ end
266
+ end
267
+
268
+ context 'variables in string interpolation' do
269
+ let(:code) { "
270
+ class test {
271
+ \"${foo.split(',')}\" # foo is a top-scope variable
272
+ \"${::bar.split(',')}\"
273
+ }
274
+ " }
275
+
276
+ it 'should only detect one problem' do
277
+ expect(problems).to have(1).problems
278
+ end
279
+
280
+ it 'should create one warning' do
281
+ expect(problems).to contain_warning(msg).on_line(3).in_column(11)
282
+ end
283
+ end
211
284
  end
@@ -79,6 +79,18 @@ describe 'unquoted_node_name' do
79
79
  expect(problems).to contain_warning(msg).on_line(1).in_column(19)
80
80
  end
81
81
  end
82
+
83
+ context 'incomplete node block' do
84
+ let(:code) { 'node foo' }
85
+
86
+ it 'should detect a problem' do
87
+ expect(problems).to have(1).problem
88
+ end
89
+
90
+ it 'should create 1 error' do
91
+ expect(problems).to contain_error('Syntax error (try running `puppet parser validate <file>`)').on_line(1).in_column(1)
92
+ end
93
+ end
82
94
  end
83
95
 
84
96
  context 'with fix enabled' do
@@ -159,5 +159,45 @@ describe 'ensure_first_param' do
159
159
  expect(problems).to have(0).problems
160
160
  end
161
161
  end
162
+
163
+ context 'ensure is a selector' do
164
+ let(:code) { "
165
+ file { 'foo':
166
+ mode => '0640',
167
+ ensure => $::operatingsystem ? {
168
+ 'redhat' => absent,
169
+ default => $::phase_of_the_moon ? {
170
+ 'full' => absent,
171
+ default => present,
172
+ },
173
+ },
174
+ }
175
+ " }
176
+
177
+ let(:fixed) { "
178
+ file { 'foo':
179
+ ensure => $::operatingsystem ? {
180
+ 'redhat' => absent,
181
+ default => $::phase_of_the_moon ? {
182
+ 'full' => absent,
183
+ default => present,
184
+ },
185
+ },
186
+ mode => '0640',
187
+ }
188
+ " }
189
+
190
+ it 'should detect a problem' do
191
+ expect(problems).to have(1).problem
192
+ end
193
+
194
+ it 'should fix the problem' do
195
+ expect(problems).to contain_fixed(msg).on_line(4).in_column(11)
196
+ end
197
+
198
+ it 'should move the whole ensure parameter to the top' do
199
+ expect(manifest).to eq(fixed)
200
+ end
201
+ end
162
202
  end
163
203
  end
@@ -131,6 +131,38 @@ describe 'file_mode' do
131
131
  expect(problems).to have(0).problems
132
132
  end
133
133
  end
134
+
135
+ context 'mode as a function return value' do
136
+ let(:code) { "file { 'foo': mode => lookup('bar'), }" }
137
+
138
+ it 'should not detect any problems' do
139
+ expect(problems).to have(0).problems
140
+ end
141
+ end
142
+
143
+ context 'multi body file bad modes selector' do
144
+ let(:code) { "
145
+ file {
146
+ '/tmp/foo1':
147
+ ensure => $foo ? { default => absent },
148
+ mode => 644;
149
+ '/tmp/foo2':
150
+ mode => 644;
151
+ '/tmp/foo3':
152
+ mode => 644;
153
+ }"
154
+ }
155
+
156
+ it 'should detect 3 problems' do
157
+ expect(problems).to have(3).problems
158
+ end
159
+
160
+ it 'should create three warnings' do
161
+ expect(problems).to contain_warning(sprintf(msg)).on_line(5).in_column(21)
162
+ expect(problems).to contain_warning(sprintf(msg)).on_line(7).in_column(21)
163
+ expect(problems).to contain_warning(sprintf(msg)).on_line(9).in_column(21)
164
+ end
165
+ end
134
166
  end
135
167
 
136
168
  context 'with fix enabled' do
@@ -205,5 +237,57 @@ describe 'file_mode' do
205
237
  expect(manifest).to eq(code)
206
238
  end
207
239
  end
240
+
241
+ context 'mode as a function return value' do
242
+ let(:code) { "file { 'foo': mode => lookup('bar'), }" }
243
+
244
+ it 'should not detect any problems' do
245
+ expect(problems).to have(0).problems
246
+ end
247
+
248
+ it 'should not change the manifest' do
249
+ expect(manifest).to eq(code)
250
+ end
251
+ end
252
+
253
+ context 'multi body file bad modes selector' do
254
+ let(:code) { "
255
+ file {
256
+ '/tmp/foo1':
257
+ ensure => $foo ? { default => absent },
258
+ mode => 644;
259
+ '/tmp/foo2':
260
+ mode => 644;
261
+ '/tmp/foo3':
262
+ mode => 644;
263
+ }"
264
+ }
265
+
266
+ let(:fixed) { "
267
+ file {
268
+ '/tmp/foo1':
269
+ ensure => $foo ? { default => absent },
270
+ mode => '0644';
271
+ '/tmp/foo2':
272
+ mode => '0644';
273
+ '/tmp/foo3':
274
+ mode => '0644';
275
+ }"
276
+ }
277
+
278
+ it 'should detect 3 problems' do
279
+ expect(problems).to have(3).problems
280
+ end
281
+
282
+ it 'should fix 3 problems' do
283
+ expect(problems).to contain_fixed(msg).on_line(5).in_column(21)
284
+ expect(problems).to contain_fixed(msg).on_line(7).in_column(21)
285
+ expect(problems).to contain_fixed(msg).on_line(9).in_column(21)
286
+ end
287
+
288
+ it 'should zero pad the file modes and change them to strings' do
289
+ expect(manifest).to eq(fixed)
290
+ end
291
+ end
208
292
  end
209
293
  end
@@ -27,6 +27,38 @@ describe 'unquoted_file_mode' do
27
27
  expect(problems).to contain_warning(msg).on_line(1).in_column(25)
28
28
  end
29
29
  end
30
+
31
+ context 'file mode from a function rvalue' do
32
+ let(:code) { "file { 'foo': mode => lookup('bar'), }" }
33
+
34
+ it 'should not detect any problems' do
35
+ expect(problems).to have(0).problems
36
+ end
37
+ end
38
+
39
+ context 'multi body file bad modes selector' do
40
+ let(:code) { "
41
+ file {
42
+ '/tmp/foo1':
43
+ ensure => $foo ? { default => absent },
44
+ mode => 644;
45
+ '/tmp/foo2':
46
+ mode => 644;
47
+ '/tmp/foo3':
48
+ mode => 644;
49
+ }"
50
+ }
51
+
52
+ it 'should detect 3 problems' do
53
+ expect(problems).to have(3).problems
54
+ end
55
+
56
+ it 'should create three warnings' do
57
+ expect(problems).to contain_warning(sprintf(msg)).on_line(5).in_column(21)
58
+ expect(problems).to contain_warning(sprintf(msg)).on_line(7).in_column(21)
59
+ expect(problems).to contain_warning(sprintf(msg)).on_line(9).in_column(21)
60
+ end
61
+ end
30
62
  end
31
63
 
32
64
  context 'with fix enabled' do
@@ -69,5 +101,57 @@ describe 'unquoted_file_mode' do
69
101
  expect(manifest).to eq("concat { 'foo': mode => '0777' }")
70
102
  end
71
103
  end
104
+
105
+ context 'file mode from a function rvalue' do
106
+ let(:code) { "file { 'foo': mode => lookup('bar'), }" }
107
+
108
+ it 'should not detect any problems' do
109
+ expect(problems).to have(0).problems
110
+ end
111
+
112
+ it 'should not change the manifest' do
113
+ expect(manifest).to eq(code)
114
+ end
115
+ end
116
+
117
+ context 'multi body file bad modes selector' do
118
+ let(:code) { "
119
+ file {
120
+ '/tmp/foo1':
121
+ ensure => $foo ? { default => absent },
122
+ mode => 644;
123
+ '/tmp/foo2':
124
+ mode => 644;
125
+ '/tmp/foo3':
126
+ mode => 644;
127
+ }"
128
+ }
129
+
130
+ let(:fixed) { "
131
+ file {
132
+ '/tmp/foo1':
133
+ ensure => $foo ? { default => absent },
134
+ mode => '644';
135
+ '/tmp/foo2':
136
+ mode => '644';
137
+ '/tmp/foo3':
138
+ mode => '644';
139
+ }"
140
+ }
141
+
142
+ it 'should detect 3 problems' do
143
+ expect(problems).to have(3).problems
144
+ end
145
+
146
+ it 'should fix 3 problems' do
147
+ expect(problems).to contain_fixed(msg).on_line(5).in_column(21)
148
+ expect(problems).to contain_fixed(msg).on_line(7).in_column(21)
149
+ expect(problems).to contain_fixed(msg).on_line(9).in_column(21)
150
+ end
151
+
152
+ it 'should quote the file modes' do
153
+ expect(manifest).to eq(fixed)
154
+ end
155
+ end
72
156
  end
73
157
  end
@@ -99,6 +99,7 @@ describe 'double_quoted_strings' do
99
99
  $string4 = "this string contains \\"escaped \\" double quotes"
100
100
  $string5 = "this string contains \\'escaped \\' single quotes"
101
101
  $string6 = "this string contains \r line return"
102
+ $string7 = "this string contains \\\\ an escaped backslash"
102
103
  }}
103
104
 
104
105
  it 'should not detect any problems' do
@@ -402,6 +402,28 @@ describe 'arrow_alignment' do
402
402
  expect(problems).to contain_warning(sprintf(msg,23,19)).on_line(6).in_column(19)
403
403
  end
404
404
  end
405
+
406
+ context 'complex data structure with different indentation levels at the same depth' do
407
+ let(:code) { "
408
+ class { 'some_class':
409
+ config_hash => {
410
+ 'a_hash' => {
411
+ 'foo' => 'bar',
412
+ },
413
+ 'an_array' => [
414
+ {
415
+ foo => 'bar',
416
+ bar => 'baz',
417
+ },
418
+ ],
419
+ },
420
+ }
421
+ " }
422
+
423
+ it 'should not detect any problems' do
424
+ expect(problems).to have(0).problems
425
+ end
426
+ end
405
427
  end
406
428
 
407
429
  context 'with fix enabled' do
@@ -675,5 +697,164 @@ describe 'arrow_alignment' do
675
697
  expect(manifest).to eq(fixed)
676
698
  end
677
699
  end
700
+
701
+ context 'complex data structure with different indentation levels at the same depth' do
702
+ let(:code) { "
703
+ class { 'some_class':
704
+ config_hash => {
705
+ 'a_hash' => {
706
+ 'foo' => 'bar',
707
+ },
708
+ 'an_array' => [
709
+ {
710
+ foo => 'bar',
711
+ bar => 'baz',
712
+ },
713
+ ],
714
+ },
715
+ }
716
+ " }
717
+
718
+ let(:fixed) { "
719
+ class { 'some_class':
720
+ config_hash => {
721
+ 'a_hash' => {
722
+ 'foo' => 'bar',
723
+ },
724
+ 'an_array' => [
725
+ {
726
+ foo => 'bar',
727
+ bar => 'baz',
728
+ },
729
+ ],
730
+ },
731
+ }
732
+ " }
733
+
734
+ it 'should detect 1 problem' do
735
+ expect(problems).to have(1).problems
736
+ end
737
+
738
+ it 'should fix 1 problem' do
739
+ expect(problems).to contain_fixed(sprintf(msg, 21, 22)).on_line(10).in_column(22)
740
+ end
741
+
742
+ it 'should align the hash rockets' do
743
+ expect(manifest).to eq(fixed)
744
+ end
745
+ end
746
+
747
+ context 'complex data structure with multiple token keys' do
748
+ let(:code) { <<-END.gsub(/^ {8}/, '')
749
+ class example (
750
+ $external_ip_base,
751
+ ) {
752
+
753
+ bar { 'xxxxxxxxx':
754
+ inputs => {
755
+ 'ny' => {
756
+ "${external_ip_base}.16:443 ${a} ${b} ${c}" => 'foo',
757
+ 'veryveryverylongstring8:443'=> 'foo',
758
+ 'simple'=> 'foo',
759
+ '3'=> :foo,
760
+ :baz=> :qux,
761
+ 3=> 3,
762
+ },
763
+ },
764
+ }
765
+ }
766
+ END
767
+ }
768
+
769
+ let(:fixed) { <<-END.gsub(/^ {8}/, '')
770
+ class example (
771
+ $external_ip_base,
772
+ ) {
773
+
774
+ bar { 'xxxxxxxxx':
775
+ inputs => {
776
+ 'ny' => {
777
+ "${external_ip_base}.16:443 ${a} ${b} ${c}" => 'foo',
778
+ 'veryveryverylongstring8:443' => 'foo',
779
+ 'simple' => 'foo',
780
+ '3' => :foo,
781
+ :baz => :qux,
782
+ 3 => 3,
783
+ },
784
+ },
785
+ }
786
+ }
787
+ END
788
+ }
789
+
790
+ it 'should detect 5 problems' do
791
+ expect(problems).to have(5).problems
792
+ end
793
+
794
+ it 'should fix 5 problems' do
795
+ expect(problems).to contain_fixed(sprintf(msg, 53, 38)).on_line(9).in_column(38)
796
+ expect(problems).to contain_fixed(sprintf(msg, 53, 17)).on_line(10).in_column(17)
797
+ expect(problems).to contain_fixed(sprintf(msg, 53, 12)).on_line(11).in_column(12)
798
+ expect(problems).to contain_fixed(sprintf(msg, 53, 13)).on_line(12).in_column(13)
799
+ expect(problems).to contain_fixed(sprintf(msg, 53, 10)).on_line(13).in_column(10)
800
+ end
801
+
802
+ it 'should realign the arrows' do
803
+ expect(manifest).to eq(fixed)
804
+ end
805
+ end
806
+
807
+ context 'realignment of resource with an inline single line hash' do
808
+ let(:code) { <<-END.gsub(/^ {8}/, '')
809
+ class { 'puppetdb':
810
+ database => 'embedded',
811
+ #database => 'postgres',
812
+ #postgres_version => '9.3',
813
+ java_args => { '-Xmx' => '512m', '-Xms' => '256m' },
814
+ listen_address => $::ipaddress_eth0,
815
+ listen_port => 4998,
816
+ ssl_listen_address => $::ipaddress_eth0,
817
+ ssl_listen_port => 4999,
818
+ open_listen_port => false,
819
+ open_ssl_listen_port => false;
820
+ }
821
+ END
822
+ }
823
+
824
+ let(:fixed) { <<-END.gsub(/^ {8}/, '')
825
+ class { 'puppetdb':
826
+ database => 'embedded',
827
+ #database => 'postgres',
828
+ #postgres_version => '9.3',
829
+ java_args => { '-Xmx' => '512m', '-Xms' => '256m' },
830
+ listen_address => $::ipaddress_eth0,
831
+ listen_port => 4998,
832
+ ssl_listen_address => $::ipaddress_eth0,
833
+ ssl_listen_port => 4999,
834
+ open_listen_port => false,
835
+ open_ssl_listen_port => false;
836
+ }
837
+ END
838
+ }
839
+
840
+ it 'should detect 8 problems' do
841
+ expect(problems).to have(8).problems
842
+ end
843
+
844
+ it 'should fix 8 problems' do
845
+ expect(problems).to contain_fixed(sprintf(msg, 24, 27)).on_line(2).in_column(27)
846
+ expect(problems).to contain_fixed(sprintf(msg, 24, 27)).on_line(5).in_column(27)
847
+ expect(problems).to contain_fixed(sprintf(msg, 24, 27)).on_line(6).in_column(27)
848
+ expect(problems).to contain_fixed(sprintf(msg, 24, 27)).on_line(7).in_column(27)
849
+ expect(problems).to contain_fixed(sprintf(msg, 24, 27)).on_line(8).in_column(27)
850
+ expect(problems).to contain_fixed(sprintf(msg, 24, 27)).on_line(9).in_column(27)
851
+ expect(problems).to contain_fixed(sprintf(msg, 24, 27)).on_line(10).in_column(27)
852
+ expect(problems).to contain_fixed(sprintf(msg, 24, 27)).on_line(11).in_column(27)
853
+ end
854
+
855
+ it 'should realign the arrows' do
856
+ expect(manifest).to eq(fixed)
857
+ end
858
+ end
678
859
  end
679
860
  end