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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.kitchen.yml +3 -0
- data/.travis.yml +64 -0
- data/.yardopts +7 -0
- data/.yo-rc.json +7 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +32 -0
- data/LICENSE +201 -0
- data/README.md +102 -0
- data/Rakefile +17 -0
- data/lib/poise_file.rb +21 -0
- data/lib/poise_file/cheftie.rb +18 -0
- data/lib/poise_file/resources.rb +27 -0
- data/lib/poise_file/resources/poise_file.rb +242 -0
- data/lib/poise_file/version.rb +21 -0
- data/poise-file.gemspec +42 -0
- data/test/cookbook/metadata.rb +18 -0
- data/test/cookbook/recipes/default.rb +36 -0
- data/test/gemfiles/chef-12.1.gemfile +23 -0
- data/test/gemfiles/chef-12.10.gemfile +23 -0
- data/test/gemfiles/chef-12.11.gemfile +23 -0
- data/test/gemfiles/chef-12.12.gemfile +22 -0
- data/test/gemfiles/chef-12.13.gemfile +22 -0
- data/test/gemfiles/chef-12.14.gemfile +19 -0
- data/test/gemfiles/chef-12.15.gemfile +19 -0
- data/test/gemfiles/chef-12.16.gemfile +19 -0
- data/test/gemfiles/chef-12.17.gemfile +19 -0
- data/test/gemfiles/chef-12.18.gemfile +19 -0
- data/test/gemfiles/chef-12.19.gemfile +19 -0
- data/test/gemfiles/chef-12.2.gemfile +23 -0
- data/test/gemfiles/chef-12.3.gemfile +23 -0
- data/test/gemfiles/chef-12.4.gemfile +24 -0
- data/test/gemfiles/chef-12.5.gemfile +23 -0
- data/test/gemfiles/chef-12.6.gemfile +23 -0
- data/test/gemfiles/chef-12.7.gemfile +23 -0
- data/test/gemfiles/chef-12.8.gemfile +23 -0
- data/test/gemfiles/chef-12.9.gemfile +23 -0
- data/test/gemfiles/chef-12.gemfile +19 -0
- data/test/gemfiles/chef-13.0.gemfile +19 -0
- data/test/gemfiles/chef-13.gemfile +19 -0
- data/test/gemfiles/master.gemfile +26 -0
- data/test/integration/default/serverspec/default_spec.rb +54 -0
- data/test/spec/resources/poise_file_spec.rb +328 -0
- data/test/spec/spec_helper.rb +19 -0
- metadata +183 -0
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
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 'poise_boiler/rakefile'
|
data/lib/poise_file.rb
ADDED
@@ -0,0 +1,21 @@
|
|
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
|
+
|
18
|
+
module PoiseFile
|
19
|
+
autoload :Resources, 'poise_file/resources'
|
20
|
+
autoload :VERSION, 'poise_file/version'
|
21
|
+
end
|
@@ -0,0 +1,18 @@
|
|
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 'poise_file/resources'
|
@@ -0,0 +1,27 @@
|
|
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 'poise_file/resources/poise_file'
|
19
|
+
|
20
|
+
|
21
|
+
module PoiseFile
|
22
|
+
# Chef resources and providers for poise-file.
|
23
|
+
#
|
24
|
+
# @since 1.0.0
|
25
|
+
module Resources
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,242 @@
|
|
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 'chef/file_content_management/content_base'
|
19
|
+
require 'chef/file_content_management/tempfile'
|
20
|
+
require 'chef/resource/file'
|
21
|
+
require 'chef/provider/file'
|
22
|
+
require 'poise'
|
23
|
+
|
24
|
+
|
25
|
+
module PoiseFile
|
26
|
+
module Resources
|
27
|
+
# (see PoiseFile::Resource)
|
28
|
+
# @since 1.0.0
|
29
|
+
module PoiseFile
|
30
|
+
# A `poise_file` resource to write out a file with some nice helpers.
|
31
|
+
#
|
32
|
+
# @provides poise_file
|
33
|
+
# @action create
|
34
|
+
# @action delete
|
35
|
+
# @action touch
|
36
|
+
# @action create_if_missing
|
37
|
+
# @example
|
38
|
+
# poise_file '/etc/myapp.json' do
|
39
|
+
# content listen: 80, debug: false
|
40
|
+
# end
|
41
|
+
class Resource < Chef::Resource::File
|
42
|
+
include Poise
|
43
|
+
provides(:poise_file)
|
44
|
+
actions(:create, :delete, :touch, :create_if_missing)
|
45
|
+
|
46
|
+
# @!attribute content
|
47
|
+
# Format to write the file in. `text` is the same as the core `file`
|
48
|
+
# resource, `json` writes the content as a JSON object, `yaml` as a
|
49
|
+
# YAML object.
|
50
|
+
# @return [String, Symbol]
|
51
|
+
attribute(:content, kind_of: [String, Hash, Array])
|
52
|
+
|
53
|
+
# @!attribute format
|
54
|
+
# Format to write the file in. `text` is the same as the core `file`
|
55
|
+
# resource, `json` writes the content as a JSON object, `yaml` as a
|
56
|
+
# YAML object.
|
57
|
+
# @return [String, Symbol]
|
58
|
+
attribute(:format, kind_of: [String, Symbol], default: lazy { default_format })
|
59
|
+
|
60
|
+
# @!attribute pattern
|
61
|
+
# Regular expression pattern to use for an in-place update of the file.
|
62
|
+
# If given a Proc it should take two arguments, the current content of
|
63
|
+
# the file and the resource object.
|
64
|
+
# @see #pattern_location
|
65
|
+
# @return [String, Regexp, Proc, nil, false]
|
66
|
+
attribute(:pattern, kind_of: [String, Regexp, Proc, NilClass, FalseClass], default: nil)
|
67
|
+
|
68
|
+
# @!attribute pattern_location
|
69
|
+
# Location to insert the {#content} data at. Must be one of:
|
70
|
+
# * replace: Overwrite the pattern.
|
71
|
+
# * replace_or_add: Overwrite the patter or append to the file if the
|
72
|
+
# pattern is not present.
|
73
|
+
# * before: Insert the {#content} immediately before the pattern if it
|
74
|
+
# doesn't already exist.
|
75
|
+
# * after: Insert the {#content} immediately after the pattern if it
|
76
|
+
# doesn't already exist.
|
77
|
+
# @see #pattern
|
78
|
+
# @return [String, Symbol]
|
79
|
+
attribute(:pattern_location, kind_of: [String, Symbol], default: 'replace_or_add')
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
# Find the default format based on the file path.
|
84
|
+
#
|
85
|
+
# @api private
|
86
|
+
# @return [String]
|
87
|
+
def default_format
|
88
|
+
# If we have a pattern, ignore the format system by default. If we
|
89
|
+
# have string content, it's just raw content by default.
|
90
|
+
return 'text' if pattern || content.is_a?(String)
|
91
|
+
case path
|
92
|
+
when /\.json$/
|
93
|
+
'json'
|
94
|
+
when /\.ya?ml$/
|
95
|
+
'yaml'
|
96
|
+
else
|
97
|
+
'text'
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# File content class for `poise_file`.
|
103
|
+
#
|
104
|
+
# @api private
|
105
|
+
# @see Resource
|
106
|
+
class Content < Chef::FileContentManagement::ContentBase
|
107
|
+
# Required abstract method for ContentBase. Builds the new content of
|
108
|
+
# file in a tempfile or returns nil to not touch the file content.
|
109
|
+
#
|
110
|
+
# @return [Chef::FileContentManagement::Tempfile, nil]
|
111
|
+
def file_for_provider
|
112
|
+
if @new_resource.content
|
113
|
+
if @new_resource.pattern && @new_resource.format.to_s != 'text'
|
114
|
+
raise ArgumentError.new("Cannot use `pattern` property and `format` property together")
|
115
|
+
end
|
116
|
+
|
117
|
+
tempfile = Chef::FileContentManagement::Tempfile.new(@new_resource).tempfile
|
118
|
+
content = if @new_resource.pattern
|
119
|
+
content_for_pattern
|
120
|
+
else
|
121
|
+
content_for_format
|
122
|
+
end
|
123
|
+
tempfile.write(content)
|
124
|
+
tempfile.close
|
125
|
+
tempfile
|
126
|
+
else
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
# Build the content when using the edit-in-place mode.
|
134
|
+
#
|
135
|
+
# @api private
|
136
|
+
# @return [String]
|
137
|
+
def content_for_pattern
|
138
|
+
# Get the base content to start from.
|
139
|
+
existing_content = if ::File.exist?(@new_resource.path)
|
140
|
+
IO.read(@new_resource.path)
|
141
|
+
else
|
142
|
+
# Pretend the file is empty if it doesn't already exist.
|
143
|
+
''
|
144
|
+
end
|
145
|
+
|
146
|
+
# If we were given a proc, use it.
|
147
|
+
if @new_resource.pattern.is_a?(Proc)
|
148
|
+
return @new_resource.pattern.call(existing_content, @new_resource)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Build the pattern.
|
152
|
+
pattern = if @new_resource.pattern.is_a?(Regexp)
|
153
|
+
# Should this dup the pattern because weird tracking stuff?
|
154
|
+
@new_resource.pattern
|
155
|
+
else
|
156
|
+
# Deal with newlines at the end of a line because $ matches before
|
157
|
+
# newline, not after.
|
158
|
+
pattern_string = if @new_resource.content.end_with?("\n")
|
159
|
+
@new_resource.pattern.gsub(/\$\Z/, "$\n?")
|
160
|
+
else
|
161
|
+
@new_resource.pattern
|
162
|
+
end
|
163
|
+
# Ruby will show a warning if trying to add options to an existing
|
164
|
+
# Regexp instance so only use that if it's a string.
|
165
|
+
Regexp.new(pattern_string, Regexp::MULTILINE)
|
166
|
+
end
|
167
|
+
|
168
|
+
# Run the pattern operation.
|
169
|
+
case @new_resource.pattern_location.to_s
|
170
|
+
when 'replace'
|
171
|
+
# Overwrite the matched section.
|
172
|
+
existing_content.gsub!(pattern, @new_resource.content) || existing_content
|
173
|
+
when 'replace_or_add'
|
174
|
+
# Overwrite the pattern if it matches otherwise append.
|
175
|
+
existing_content.gsub!(pattern, @new_resource.content) || (existing_content << @new_resource.content)
|
176
|
+
when 'before'
|
177
|
+
# Insert the content before the pattern if it doesn't already exist.
|
178
|
+
match = pattern.match(existing_content)
|
179
|
+
if match
|
180
|
+
if match.pre_match.end_with?(@new_resource.content)
|
181
|
+
existing_content
|
182
|
+
else
|
183
|
+
'' << match.pre_match << @new_resource.content << match[0] << match.post_match
|
184
|
+
end
|
185
|
+
else
|
186
|
+
existing_content
|
187
|
+
end
|
188
|
+
when 'after'
|
189
|
+
# Insert the content after the pattern if it doesn't already exist.
|
190
|
+
match = pattern.match(existing_content)
|
191
|
+
if match
|
192
|
+
if match.post_match.start_with?(@new_resource.content)
|
193
|
+
existing_content
|
194
|
+
else
|
195
|
+
'' << match.pre_match << match[0] << @new_resource.content << match.post_match
|
196
|
+
end
|
197
|
+
else
|
198
|
+
existing_content
|
199
|
+
end
|
200
|
+
else
|
201
|
+
raise ArgumentError.new("Unknown file pattern location #{@new_resource.pattern_location.inspect}")
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# Build the content when using format mode (i.e. when not using the
|
206
|
+
# edit-in-place mode).
|
207
|
+
#
|
208
|
+
# @api private
|
209
|
+
# @return [String]
|
210
|
+
def content_for_format
|
211
|
+
case @new_resource.format.to_s
|
212
|
+
when 'json'
|
213
|
+
require 'chef/json_compat'
|
214
|
+
# Make sure we include the trailing newline because YAML has one.
|
215
|
+
Chef::JSONCompat.to_json_pretty(@new_resource.content) + "\n"
|
216
|
+
when 'yaml'
|
217
|
+
require 'yaml'
|
218
|
+
YAML.dump(@new_resource.content)
|
219
|
+
when 'text'
|
220
|
+
@new_resource.content
|
221
|
+
else
|
222
|
+
raise ArgumentError.new("Unknown file format #{@new_resource.format.inspect}")
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
# Provider for `poise_file`.
|
228
|
+
#
|
229
|
+
# @see Resource
|
230
|
+
# @provides poise_file
|
231
|
+
class Provider < Chef::Provider::File
|
232
|
+
include Poise
|
233
|
+
provides(:poise_file)
|
234
|
+
|
235
|
+
def initialize(new_resource, run_context)
|
236
|
+
@content_class = Content
|
237
|
+
super
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
@@ -0,0 +1,21 @@
|
|
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
|
+
|
19
|
+
module PoiseFile
|
20
|
+
VERSION = '1.0.0'
|
21
|
+
end
|
data/poise-file.gemspec
ADDED
@@ -0,0 +1,42 @@
|
|
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
|
+
lib = File.expand_path('../lib', __FILE__)
|
18
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
19
|
+
require 'poise_file/version'
|
20
|
+
|
21
|
+
Gem::Specification.new do |spec|
|
22
|
+
spec.name = 'poise-file'
|
23
|
+
spec.version = PoiseFile::VERSION
|
24
|
+
spec.authors = ['Noah Kantrowitz']
|
25
|
+
spec.email = %w{noah@coderanger.net}
|
26
|
+
spec.description = 'A Chef cookbook for advanced file managent.'
|
27
|
+
spec.summary = spec.description
|
28
|
+
spec.homepage = 'https://github.com/poise/poise-file'
|
29
|
+
spec.license = 'Apache-2.0'
|
30
|
+
spec.metadata['platforms'] = 'any'
|
31
|
+
|
32
|
+
spec.files = `git ls-files`.split($/)
|
33
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
34
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
35
|
+
spec.require_paths = %w{lib}
|
36
|
+
|
37
|
+
spec.add_dependency 'chef', '>= 12.1', '< 14'
|
38
|
+
spec.add_dependency 'halite', '~> 1.0'
|
39
|
+
spec.add_dependency 'poise', '~> 2.0'
|
40
|
+
|
41
|
+
spec.add_development_dependency 'poise-boiler', '~> 1.0'
|
42
|
+
end
|
@@ -0,0 +1,18 @@
|
|
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
|
+
name 'poise-file_test'
|
18
|
+
depends 'poise-file'
|
@@ -0,0 +1,36 @@
|
|
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
|
+
poise_file '/poise_test' do
|
18
|
+
content "I'm a little teapot\n"
|
19
|
+
end
|
20
|
+
|
21
|
+
poise_file '/poise_test.json' do
|
22
|
+
content ['short and stout', {here: 'is my handle'}]
|
23
|
+
end
|
24
|
+
|
25
|
+
poise_file '/poise_test.yml' do
|
26
|
+
content 'here' => 'is my spout', 'when' => ['I', 'get', 'all', 'steamed', 'up']
|
27
|
+
end
|
28
|
+
|
29
|
+
file '/poise_test_pattern' do
|
30
|
+
content "I must shout\ntip me over\n"
|
31
|
+
end
|
32
|
+
|
33
|
+
poise_file '/poise_test_pattern' do
|
34
|
+
content 'yell'
|
35
|
+
pattern 'shout'
|
36
|
+
end
|