diff options
author | Daniel DeLeo <dan@opscode.com> | 2011-03-22 15:26:58 -0700 |
---|---|---|
committer | Daniel DeLeo <dan@opscode.com> | 2011-03-22 15:31:25 -0700 |
commit | 06396d20ea553c5a369d03617d62dbe4db222d26 (patch) | |
tree | 0544ccda1fc6f3e66e825406efbfec917fbae263 /chef/lib/chef/knife/node_edit.rb | |
parent | b3c8018f17a3f9be7436187f76c299bcaca62f87 (diff) | |
download | chef-06396d20ea553c5a369d03617d62dbe4db222d26.tar.gz |
[CHEF-2126] Don't show irrelevant attributes in knife node edit
Diffstat (limited to 'chef/lib/chef/knife/node_edit.rb')
-rw-r--r-- | chef/lib/chef/knife/node_edit.rb | 130 |
1 files changed, 123 insertions, 7 deletions
diff --git a/chef/lib/chef/knife/node_edit.rb b/chef/lib/chef/knife/node_edit.rb index 9c3772cfb4..29e536e460 100644 --- a/chef/lib/chef/knife/node_edit.rb +++ b/chef/lib/chef/knife/node_edit.rb @@ -6,9 +6,9 @@ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,20 +22,136 @@ require 'chef/json_compat' class Chef class Knife + + module NodeEditController + def edit_node + abort "You specified the --no-editor option, nothing to edit" if config[:no_editor] + assert_editor_set! + + updated_node_data = edit_data(view) + apply_updates(updated_node_data) + @updated_node + end + + def view + result = {} + result["name"] = node.name + result["chef_environment"] = node.chef_environment + result["normal"] = node.normal_attrs + result["run_list"] = node.run_list + + if config[:all_attributes] + result["default"] = node.default_attrs + result["override"] = node.override_attrs + result["automatic"] = node.automatic_attrs + end + Chef::JSONCompat.to_json_pretty(result) + end + + def edit_data(text) + edited_data = tempfile_for(text) {|filename| system("#{config[:editor]} #{filename}")} + Chef::JSONCompat.from_json(edited_data) + end + + def apply_updates(updated_data) + # TODO: should warn/error/ask for confirmation when changing the + # name, since this results in a new node, not an edited node. + @updated_node = Node.new.tap do |n| + n.name( updated_data["name"] ) + n.chef_environment( updated_data["chef_environment"] ) + n.run_list( updated_data["run_list"]) + n.normal_attrs = updated_data["normal"] + + if config[:all_attributes] + n.default_attrs = updated_data["default"] + n.override_attrs = updated_data["override"] + n.automatic_attrs = updated_data["automatic"] + else + n.default_attrs = node.default_attrs + n.override_attrs = node.override_attrs + n.automatic_attrs = node.automatic_attrs + end + end + end + + def updated? + pristine_copy = Chef::JSONCompat.from_json(Chef::JSONCompat.to_json(node), :create_additions => false) + updated_copy = Chef::JSONCompat.from_json(Chef::JSONCompat.to_json(@updated_node), :create_additions => false) + unless pristine_copy == updated_copy + updated_properties = %w{name normal chef_environment run_list default override automatic}.reject do |key| + pristine_copy[key] == updated_copy[key] + end + end + ( pristine_copy != updated_copy ) && updated_properties + end + + private + + def abort(message) + STDERR.puts("ERROR: #{message}") + exit 1 + end + + def assert_editor_set! + unless config[:editor] + abort "You must set your EDITOR environment variable or configure your editor via knife.rb" + end + end + + def tempfile_for(data) + # TODO: include useful info like the node name in the temp file + # name + basename = "knife-edit-" << rand(1_000_000_000_000_000).to_s.rjust(15, '0') << '.js' + filename = File.join(Dir.tmpdir, basename) + File.open(filename, "w+") do |f| + f.sync = true + f.puts data + end + + yield filename + + IO.read(filename) + ensure + File.unlink(filename) + end + end + class NodeEdit < Knife + include NodeEditController + + attr_reader :node_name + attr_reader :node banner "knife node edit NODE (options)" - def run - @node_name = @name_args[0] + option :all_attributes, + :short => "-a", + :long => "--all", + :boolean => true, + :description => "Display all attributes when editing" + + def run + node_name = @name_args[0] - if @node_name.nil? + if node_name.nil? show_usage Chef::Log.fatal("You must specify a node name") exit 1 end - - edit_object(Chef::Node, @node_name) + + load_node(node_name) + updated_node = edit_node + if updated_values = updated? + Log.info "Saving updated #{updated_values.join(', ')} on node #{node.name}" + updated_node.save + else + Log.info "Node not updated, skipping node save" + end + end + + def load_node(node_name) + @node = Chef::Node.load(node_name) + # TODO: rescue errors with a helpful message end end end |