poise-file 1.0.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.
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