Class: Chef::Knife::ScribeAdjust
- Inherits:
-
Chef::Knife
show all
- Includes:
- Mixin::DeepMerge, Mixin::ShellOut
- Defined in:
- lib/chef/knife/scribe_adjust.rb
Constant Summary
collapse
- TEMPLATE_HASH =
{ "author_name" => "",
"author_email" => "",
"description" => "",
"adjustments" => []
}
- ENVIRONMENT_ADJUSTMENT_TEMPLATE =
{
"action" => "merge",
"type" => "environment",
"search" => "name:my_environment_name",
"adjustment" => { "default_attributes" => { },
"override_attributes" => { },
"cookbook_versions" => { }
}
}
- ROLE_ADJUSTMENT_TEMPLATE =
{
"action" => "merge",
"type" => "role",
"search" => "name:my_role_name",
"adjustment" => { "default_attributes" => { },
"override_attributes" => { },
"run_list" => [ ]
}
}
- NODE_ADJUSTMENT_TEMPLATE =
{
"action" => "merge",
"type" => "node",
"search" => "name:my_node_name",
"adjustment" => { "normal" => { },
"run_list" => [ ],
}
}
Instance Method Summary
collapse
Methods inherited from Chef::Knife
#deep_delete, #deep_delete!, #diff
Instance Method Details
#action_overwrite(base, overwrite_with) ⇒ Object
297
298
299
300
301
302
303
304
305
|
# File 'lib/chef/knife/scribe_adjust.rb', line 297
def action_overwrite(base, overwrite_with)
if base.kind_of?(Hash) && overwrite_with.kind_of?(Hash)
base.merge(overwrite_with)
elsif overwrite_with.nil?
base
else
overwrite_with
end
end
|
#adjustment_file_valid?(adjustment_file) ⇒ Boolean
235
236
237
238
239
240
241
242
243
244
245
246
|
# File 'lib/chef/knife/scribe_adjust.rb', line 235
def adjustment_file_valid? adjustment_file
unless adjustment_file.kind_of?(Hash)
errors.last["general"] = "Adjustment file must contain a JSON hash!"
return false
end
unless adjustment_file["adjustments"].kind_of?(Array)
errors.last["general"] = "Adjustment file must contain an array of adjustments!"
return false
end
true
end
|
#adjustment_valid?(adjustment, index) ⇒ Boolean
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
|
# File 'lib/chef/knife/scribe_adjust.rb', line 248
def adjustment_valid?(adjustment, index)
unless adjustment.kind_of?(Hash)
errors.last["adjustments"].store(index,"Adjustment must be a JSON hash!")
return false
end
["action", "type", "search", "adjustment"].each do |required_key|
unless adjustment.has_key?(required_key)
errors.last["adjustments"].store(index, "Adjustment hash must contain " + required_key + "!")
return false
end
end
unless respond_to?("action_" + adjustment["action"])
errors.last["adjustments"].store(index, "Incorrect action!")
return false
end
true
end
|
#apply_adjustment(adjustment) ⇒ Object
201
202
203
204
205
206
207
208
|
# File 'lib/chef/knife/scribe_adjust.rb', line 201
def apply_adjustment(adjustment)
query = adjustment["search"].include?(":") ? adjustment["search"] : "name:" + adjustment["search"]
Chef::Search::Query.new.search(adjustment["type"], query ) do |result|
key = result.class.name.downcase + ":" + result.name
prepared_hash = prepare_adjustment_subject(key, result)
changes[key].store("adjusted", send(("action_" + adjustment["action"]).to_sym, prepared_hash, adjustment["adjustment"]))
end
end
|
#changes ⇒ Object
119
120
121
|
# File 'lib/chef/knife/scribe_adjust.rb', line 119
def changes
@changes ||= {}
end
|
#descriptions ⇒ Object
123
124
125
|
# File 'lib/chef/knife/scribe_adjust.rb', line 123
def descriptions
@descriptions ||= []
end
|
#errors ⇒ Object
127
128
129
|
# File 'lib/chef/knife/scribe_adjust.rb', line 127
def errors
@errors ||= []
end
|
#errors? ⇒ Boolean
283
284
285
286
|
# File 'lib/chef/knife/scribe_adjust.rb', line 283
def errors?
errors.each { |err| return true if !err["general"].nil? || (err["adjustments"].size > 0) }
false
end
|
#generate_template(filename) ⇒ Object
170
171
172
173
174
175
176
177
|
# File 'lib/chef/knife/scribe_adjust.rb', line 170
def generate_template(filename)
unless ["environment", "role", "node"].include?(config[:type])
ui.fatal("Incorrect adjustment type! Only 'node', 'environment' or 'role' allowed.")
exit 1
end
TEMPLATE_HASH["adjustments"] = [self.class.class_eval(config[:type].upcase + "_ADJUSTMENT_TEMPLATE")]
File.open(filename, "w") { |file| file.write(JSON.pretty_generate(TEMPLATE_HASH)) }
end
|
#generate_templates ⇒ Object
145
146
147
|
# File 'lib/chef/knife/scribe_adjust.rb', line 145
def generate_templates
end
|
#hire ⇒ Object
268
269
270
271
272
|
# File 'lib/chef/knife/scribe_adjust.rb', line 268
def hire
hired_scribe = Chef::Knife::ScribeHire.new
[:chronicle_path, :remote_url, :remote_name].each { |key| hired_scribe.config[key] = config[key] }
hired_scribe.run
end
|
#parse_adjustment_file(filename) ⇒ Object
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
|
# File 'lib/chef/knife/scribe_adjust.rb', line 179
def parse_adjustment_file(filename)
if !File.exists?(filename)
errors.last["general"] = "File does not exist!"
else
begin
adjustment_file = File.open(filename, "r") { |file| JSON.load(file) }
if adjustment_file_valid? adjustment_file
adjustment_file["adjustments"].each_with_index do |adjustment, index|
apply_adjustment(adjustment) if adjustment_valid?(adjustment, index)
end
end
if adjustment_file["adjustments"].length > errors.last["adjustments"].length
description = adjustment_file["description"]
description += "[with errors]" if errors.last["adjustments"].size > 0
descriptions.push(description)
end
rescue JSON::ParserError
errors.last["general"] = "Malformed JSON!"
end
end
end
|
#parse_adjustments ⇒ Object
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
# File 'lib/chef/knife/scribe_adjust.rb', line 149
def parse_adjustments
@name_args.each do |filename|
errors.push({ "name" => filename, "general" => nil, "adjustments" => {} })
parse_adjustment_file(filename)
end
if errors?
print_errors
exit 1 unless config[:dryrun]
end
if config[:dryrun]
diff
else
if config[:document] == true
hire
record_state
end
write_adjustments
record_state(descriptions.join("\n").strip) if config[:document] == true
end
end
|
#prepare_adjustment_subject(key, chef_object) ⇒ Object
210
211
212
213
214
215
216
217
218
|
# File 'lib/chef/knife/scribe_adjust.rb', line 210
def prepare_adjustment_subject(key, chef_object)
prepared_hash = prepare_object_hash(chef_object)
if changes.has_key? key
prepared_hash = changes[key]["adjusted"]
else
changes.store(key, { "original" => prepared_hash })
end
prepared_hash
end
|
#prepare_object_hash(chef_object) ⇒ Object
220
221
222
223
224
225
226
227
|
# File 'lib/chef/knife/scribe_adjust.rb', line 220
def prepare_object_hash(chef_object)
prepared_hash = chef_object.to_hash
if prepared_hash["chef_type"] == "node"
prepared_hash.reject! { |key, value| !(["name","chef_type","chef_environment","run_list"].include? key) }
prepared_hash.merge!({ "normal" => chef_object.normal_attrs })
end
prepared_hash
end
|
#print_errors ⇒ Object
288
289
290
291
292
293
294
295
|
# File 'lib/chef/knife/scribe_adjust.rb', line 288
def print_errors
ui.error("ERRORS OCCURED:")
errors.each do |err|
ui.error(err["name"]) if !err["general"].nil? || (err["adjustments"].size > 0)
ui.error("\t" + err["general"]) if !err["general"].nil?
err["adjustments"].each { |num, adj_err| ui.error("\t[Adjustment #{num}]: #{adj_err}") }
end
end
|
#record_state(message = nil) ⇒ Object
274
275
276
277
278
279
280
281
|
# File 'lib/chef/knife/scribe_adjust.rb', line 274
def record_state(message = nil)
if @copyist.nil?
@copyist = Chef::Knife::ScribeCopy.new
[:chronicle_path, :remote_name, :branch].each { |key| @copyist.config[key] = config[key] }
end
@copyist.config[:message] = message
@copyist.run
end
|
#run ⇒ Object
132
133
134
135
136
137
138
139
140
141
142
143
|
# File 'lib/chef/knife/scribe_adjust.rb', line 132
def run
if @name_args[0].nil?
show_usage
ui.fatal("At least one adjustment file needs to be specified!")
exit 1
end
if config[:generate] == true
@name_args.each { |filename| generate_template(filename) }
else
parse_adjustments
end
end
|
#write_adjustments ⇒ Object
229
230
231
232
233
|
# File 'lib/chef/knife/scribe_adjust.rb', line 229
def write_adjustments
changes.values.each do |change|
Chef.const_get(change["adjusted"]["chef_type"].capitalize).json_create(change["adjusted"]).save
end
end
|