summaryrefslogtreecommitdiff
path: root/chef/lib/chef/knife/node_edit.rb
diff options
context:
space:
mode:
authorDaniel DeLeo <dan@opscode.com>2011-03-22 15:26:58 -0700
committerDaniel DeLeo <dan@opscode.com>2011-03-22 15:31:25 -0700
commit06396d20ea553c5a369d03617d62dbe4db222d26 (patch)
tree0544ccda1fc6f3e66e825406efbfec917fbae263 /chef/lib/chef/knife/node_edit.rb
parentb3c8018f17a3f9be7436187f76c299bcaca62f87 (diff)
downloadchef-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.rb130
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