puppet-lint 2.1.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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