poise-file 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.kitchen.yml +3 -0
  4. data/.travis.yml +64 -0
  5. data/.yardopts +7 -0
  6. data/.yo-rc.json +7 -0
  7. data/CHANGELOG.md +5 -0
  8. data/Gemfile +32 -0
  9. data/LICENSE +201 -0
  10. data/README.md +102 -0
  11. data/Rakefile +17 -0
  12. data/lib/poise_file.rb +21 -0
  13. data/lib/poise_file/cheftie.rb +18 -0
  14. data/lib/poise_file/resources.rb +27 -0
  15. data/lib/poise_file/resources/poise_file.rb +242 -0
  16. data/lib/poise_file/version.rb +21 -0
  17. data/poise-file.gemspec +42 -0
  18. data/test/cookbook/metadata.rb +18 -0
  19. data/test/cookbook/recipes/default.rb +36 -0
  20. data/test/gemfiles/chef-12.1.gemfile +23 -0
  21. data/test/gemfiles/chef-12.10.gemfile +23 -0
  22. data/test/gemfiles/chef-12.11.gemfile +23 -0
  23. data/test/gemfiles/chef-12.12.gemfile +22 -0
  24. data/test/gemfiles/chef-12.13.gemfile +22 -0
  25. data/test/gemfiles/chef-12.14.gemfile +19 -0
  26. data/test/gemfiles/chef-12.15.gemfile +19 -0
  27. data/test/gemfiles/chef-12.16.gemfile +19 -0
  28. data/test/gemfiles/chef-12.17.gemfile +19 -0
  29. data/test/gemfiles/chef-12.18.gemfile +19 -0
  30. data/test/gemfiles/chef-12.19.gemfile +19 -0
  31. data/test/gemfiles/chef-12.2.gemfile +23 -0
  32. data/test/gemfiles/chef-12.3.gemfile +23 -0
  33. data/test/gemfiles/chef-12.4.gemfile +24 -0
  34. data/test/gemfiles/chef-12.5.gemfile +23 -0
  35. data/test/gemfiles/chef-12.6.gemfile +23 -0
  36. data/test/gemfiles/chef-12.7.gemfile +23 -0
  37. data/test/gemfiles/chef-12.8.gemfile +23 -0
  38. data/test/gemfiles/chef-12.9.gemfile +23 -0
  39. data/test/gemfiles/chef-12.gemfile +19 -0
  40. data/test/gemfiles/chef-13.0.gemfile +19 -0
  41. data/test/gemfiles/chef-13.gemfile +19 -0
  42. data/test/gemfiles/master.gemfile +26 -0
  43. data/test/integration/default/serverspec/default_spec.rb +54 -0
  44. data/test/spec/resources/poise_file_spec.rb +328 -0
  45. data/test/spec/spec_helper.rb +19 -0
  46. metadata +183 -0
@@ -0,0 +1,19 @@
1
+ #
2
+ # Copyright 2017, Noah Kantrowitz
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ eval_gemfile File.expand_path('../../../Gemfile', __FILE__)
18
+
19
+ gem 'chef', '~> 13.0.118'
@@ -0,0 +1,19 @@
1
+ #
2
+ # Copyright 2017, Noah Kantrowitz
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ eval_gemfile File.expand_path('../../../Gemfile', __FILE__)
18
+
19
+ gem 'chef', '~> 13.0'
@@ -0,0 +1,26 @@
1
+ #
2
+ # Copyright 2017, Noah Kantrowitz
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ eval_gemfile File.expand_path('../../../Gemfile', __FILE__)
18
+
19
+ gem 'chef', git: 'https://github.com/chef/chef.git'
20
+ gem 'chefspec', git: 'https://github.com/sethvargo/chefspec.git'
21
+ gem 'fauxhai', git: 'https://github.com/customink/fauxhai.git'
22
+ gem 'foodcritic', git: 'https://github.com/foodcritic/foodcritic.git'
23
+ gem 'halite', git: 'https://github.com/poise/halite.git'
24
+ gem 'ohai', git: 'https://github.com/chef/ohai.git'
25
+ gem 'poise', git: 'https://github.com/poise/poise.git'
26
+ gem 'poise-boiler', git: 'https://github.com/poise/poise-boiler.git'
@@ -0,0 +1,54 @@
1
+ #
2
+ # Copyright 2017, Noah Kantrowitz
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'serverspec'
18
+ set :backend, :exec
19
+
20
+ describe file('/poise_test') do
21
+ it { is_expected.to be_a_file }
22
+ its(:content) { is_expected.to eq "I'm a little teapot\n" }
23
+ end
24
+
25
+ describe file('/poise_test.json') do
26
+ it { is_expected.to be_a_file }
27
+ its(:content) { is_expected.to eq <<-EOH }
28
+ [
29
+ "short and stout",
30
+ {
31
+ "here": "is my handle"
32
+ }
33
+ ]
34
+ EOH
35
+ end
36
+
37
+ describe file('/poise_test.yml') do
38
+ it { is_expected.to be_a_file }
39
+ its(:content) { is_expected.to eq <<-EOH }
40
+ ---
41
+ here: is my spout
42
+ when:
43
+ - I
44
+ - get
45
+ - all
46
+ - steamed
47
+ - up
48
+ EOH
49
+ end
50
+
51
+ describe file('/poise_test_pattern') do
52
+ it { is_expected.to be_a_file }
53
+ its(:content) { is_expected.to eq "I must yell\ntip me over\n" }
54
+ end
@@ -0,0 +1,328 @@
1
+ #
2
+ # Copyright 2017, Noah Kantrowitz
3
+ #
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'spec_helper'
19
+
20
+ describe PoiseFile::Resources::PoiseFile do
21
+ step_into(:poise_file)
22
+ let(:existing_content) { nil }
23
+ around do |ex|
24
+ Dir.mktmpdir('poise_file') do |path|
25
+ ex.metadata[:poise_file_temp_path] = path
26
+ default_attributes['temp_path'] = path
27
+ IO.write("#{temp_path}/test.txt", existing_content) if existing_content
28
+ ex.run
29
+ end
30
+ end
31
+
32
+ let(:temp_path) do |example|
33
+ example.metadata[:poise_file_temp_path]
34
+ end
35
+
36
+ subject do
37
+ # Actually write out the file.
38
+ run_chef
39
+ # Lazy load any requested file.
40
+ Hash.new {|has, key| IO.read("#{temp_path}/#{key}") }
41
+ end
42
+
43
+ describe 'formats' do
44
+ context 'with a .json path' do
45
+ recipe(subject: false) do
46
+ poise_file "#{node['temp_path']}/test.json" do
47
+ content foo: 'bar'
48
+ end
49
+ end
50
+
51
+ its(['test.json']) { is_expected.to eq %Q({\n "foo": "bar"\n}\n) }
52
+ end # /context with a .json path
53
+
54
+ context 'with a .json path but string content' do
55
+ recipe(subject: false) do
56
+ poise_file "#{node['temp_path']}/test.json" do
57
+ content "foo\nbar\n"
58
+ end
59
+ end
60
+
61
+ its(['test.json']) { is_expected.to eq "foo\nbar\n" }
62
+ end # /context with a .json path but string content
63
+
64
+ context 'with a .yaml path' do
65
+ recipe(subject: false) do
66
+ poise_file "#{node['temp_path']}/test.yaml" do
67
+ content 'foo' => 'bar'
68
+ end
69
+ end
70
+
71
+ its(['test.yaml']) { is_expected.to eq %Q(---\nfoo: bar\n) }
72
+ end # /context with a .yaml path
73
+
74
+ context 'with a .yml path' do
75
+ recipe(subject: false) do
76
+ poise_file "#{node['temp_path']}/test.yml" do
77
+ content 'foo' => 'bar'
78
+ end
79
+ end
80
+
81
+ its(['test.yml']) { is_expected.to eq %Q(---\nfoo: bar\n) }
82
+ end # /context with a .yml path
83
+
84
+ context 'with a .txt path' do
85
+ recipe(subject: false) do
86
+ poise_file "#{node['temp_path']}/test.txt" do
87
+ content 'foo' => 'bar'
88
+ end
89
+ end
90
+
91
+ its(['test.txt']) { is_expected.to eq %Q({"foo"=>"bar"}) }
92
+ end # /context with a .txt path
93
+
94
+ context 'with node attributes' do
95
+ recipe(subject: false) do
96
+ poise_file "#{node['temp_path']}/test.txt" do
97
+ content node['network']
98
+ end
99
+ end
100
+
101
+ its(['test.txt']) { is_expected.to match /\A\{.*\}\Z/ }
102
+ end # /context with node attributes
103
+
104
+ context 'with an invalid format' do
105
+ recipe do
106
+ poise_file "#{node['temp_path']}/test.txt" do
107
+ content "this is a test\n"
108
+ format :other
109
+ end
110
+ end
111
+
112
+ it { expect { run_chef }.to raise_error ArgumentError }
113
+ end # /context with an invalid format
114
+ end # /describe formats
115
+
116
+ describe 'patterns' do
117
+ describe 'replace' do
118
+ context 'with a simple pattern' do
119
+ let(:existing_content) { "this is\na test\n" }
120
+ recipe(subject: false) do
121
+ poise_file "#{node['temp_path']}/test.txt" do
122
+ content "this is not\n"
123
+ pattern '^this is$'
124
+ pattern_location :replace
125
+ end
126
+ end
127
+
128
+ its(['test.txt']) { is_expected.to eq "this is not\na test\n" }
129
+ end # /context with a simple pattern
130
+
131
+ context 'with a replacement without a newline' do
132
+ let(:existing_content) { "this is\na test\n" }
133
+ recipe(subject: false) do
134
+ poise_file "#{node['temp_path']}/test.txt" do
135
+ content "this is not"
136
+ pattern '^this is$'
137
+ pattern_location :replace
138
+ end
139
+ end
140
+
141
+ its(['test.txt']) { is_expected.to eq "this is not\na test\n" }
142
+ end # /context with a replacement without a newline
143
+
144
+ context 'with a pattern that does not match' do
145
+ let(:existing_content) { "this is\na test\n" }
146
+ recipe(subject: false) do
147
+ poise_file "#{node['temp_path']}/test.txt" do
148
+ content "this is not"
149
+ pattern '^this was$'
150
+ pattern_location :replace
151
+ end
152
+ end
153
+
154
+ its(['test.txt']) { is_expected.to eq "this is\na test\n" }
155
+ end # /context with a pattern that does not match
156
+ end # /describe replace
157
+
158
+ describe 'replace_or_add' do
159
+ context 'with a simple pattern' do
160
+ let(:existing_content) { "this is\na test\n" }
161
+ recipe(subject: false) do
162
+ poise_file "#{node['temp_path']}/test.txt" do
163
+ content "this is not\n"
164
+ pattern '^this is$'
165
+ pattern_location :replace_or_add
166
+ end
167
+ end
168
+
169
+ its(['test.txt']) { is_expected.to eq "this is not\na test\n" }
170
+ end # /context with a simple pattern
171
+
172
+ context 'with a patten that does not match' do
173
+ let(:existing_content) { "this is\na test\n" }
174
+ recipe(subject: false) do
175
+ poise_file "#{node['temp_path']}/test.txt" do
176
+ content "this is not\n"
177
+ pattern '^this was$'
178
+ pattern_location :replace_or_add
179
+ end
180
+ end
181
+
182
+ its(['test.txt']) { is_expected.to eq "this is\na test\nthis is not\n" }
183
+ end # /context with a patten that does not match
184
+
185
+ context 'with a file that does not exist' do
186
+ recipe(subject: false) do
187
+ poise_file "#{node['temp_path']}/test.txt" do
188
+ content "this is not\n"
189
+ pattern '^this was$'
190
+ pattern_location :replace_or_add
191
+ end
192
+ end
193
+
194
+ its(['test.txt']) { is_expected.to eq "this is not\n" }
195
+ end # /context with a file that does not exist
196
+ end # /describe replace_or_add
197
+
198
+ describe 'before' do
199
+ context 'with a simple pattern' do
200
+ let(:existing_content) { "this is\na test\n" }
201
+ recipe(subject: false) do
202
+ poise_file "#{node['temp_path']}/test.txt" do
203
+ content "probably\n"
204
+ pattern '^a test$'
205
+ pattern_location :before
206
+ end
207
+ end
208
+
209
+ its(['test.txt']) { is_expected.to eq "this is\nprobably\na test\n" }
210
+ end # /context with a simple pattern
211
+
212
+ context 'with a pattern that already matches' do
213
+ let(:existing_content) { "this is\nprobably\na test\n" }
214
+ recipe(subject: false) do
215
+ poise_file "#{node['temp_path']}/test.txt" do
216
+ content "probably\n"
217
+ pattern '^a test$'
218
+ pattern_location :before
219
+ end
220
+ end
221
+
222
+ its(['test.txt']) { is_expected.to eq "this is\nprobably\na test\n" }
223
+ end # /context with a pattern that already matches
224
+
225
+ context 'with a pattern that does not match' do
226
+ let(:existing_content) { "this is\na test\n" }
227
+ recipe(subject: false) do
228
+ poise_file "#{node['temp_path']}/test.txt" do
229
+ content "probably\n"
230
+ pattern '^not a test$'
231
+ pattern_location :before
232
+ end
233
+ end
234
+
235
+ its(['test.txt']) { is_expected.to eq "this is\na test\n" }
236
+ end # /context with a pattern that does not match
237
+ end # /describe before
238
+
239
+ describe 'after' do
240
+ context 'with a simple pattern' do
241
+ let(:existing_content) { "this is\na test\n" }
242
+ recipe(subject: false) do
243
+ poise_file "#{node['temp_path']}/test.txt" do
244
+ content "probably\n"
245
+ pattern '^a test$'
246
+ pattern_location :after
247
+ end
248
+ end
249
+
250
+ its(['test.txt']) { is_expected.to eq "this is\na test\nprobably\n" }
251
+ end # /context with a simple pattern
252
+
253
+ context 'with a pattern that already matches' do
254
+ let(:existing_content) { "this is\na test\nprobably\n" }
255
+ recipe(subject: false) do
256
+ poise_file "#{node['temp_path']}/test.txt" do
257
+ content "probably\n"
258
+ pattern '^a test$'
259
+ pattern_location :after
260
+ end
261
+ end
262
+
263
+ its(['test.txt']) { is_expected.to eq "this is\na test\nprobably\n" }
264
+ end # /context with a pattern that already matches
265
+
266
+ context 'with a pattern that does not match' do
267
+ let(:existing_content) { "this is\na test\n" }
268
+ recipe(subject: false) do
269
+ poise_file "#{node['temp_path']}/test.txt" do
270
+ content "probably\n"
271
+ pattern '^not a test$'
272
+ pattern_location :after
273
+ end
274
+ end
275
+
276
+ its(['test.txt']) { is_expected.to eq "this is\na test\n" }
277
+ end # /context with a pattern that does not match
278
+ end # /describe after
279
+
280
+ context 'with a proc pattern' do
281
+ let(:existing_content) { "this is\na test\n" }
282
+ recipe(subject: false) do
283
+ poise_file "#{node['temp_path']}/test.txt" do
284
+ content "this is not"
285
+ pattern proc {|existing_content| existing_content.gsub(/t/, 'q') }
286
+ end
287
+ end
288
+
289
+ its(['test.txt']) { is_expected.to eq "qhis is\na qesq\n" }
290
+ end # /context with a proc pattern
291
+
292
+ context 'with a RegExp pattern' do
293
+ let(:existing_content) { "this is\na test\n" }
294
+ recipe(subject: false) do
295
+ poise_file "#{node['temp_path']}/test.txt" do
296
+ content "this is not\n"
297
+ pattern(/^this is$/)
298
+ end
299
+ end
300
+
301
+ its(['test.txt']) { is_expected.to eq "this is not\n\na test\n" }
302
+ end # /context with a RegExp pattern
303
+
304
+ context 'with an invalid pattern_location' do
305
+ recipe do
306
+ poise_file "#{node['temp_path']}/test.txt" do
307
+ content "this is a test\n"
308
+ pattern 'asdf'
309
+ pattern_location :other
310
+ end
311
+ end
312
+
313
+ it { expect { run_chef }.to raise_error ArgumentError }
314
+ end # /context with an invalid pattern_location
315
+ end # /describe patterns
316
+
317
+ context 'with both a format and a pattern' do
318
+ recipe do
319
+ poise_file "#{node['temp_path']}/test.txt" do
320
+ content "this is a test\n"
321
+ format :json
322
+ pattern 'asdf'
323
+ end
324
+ end
325
+
326
+ it { expect { run_chef }.to raise_error ArgumentError }
327
+ end # /context with both a format and a pattern
328
+ end