lib/chef/knife/topo_export.rb in knife-topo-1.1.2 vs lib/chef/knife/topo_export.rb in knife-topo-2.0.1

- old
+ new

@@ -15,162 +15,137 @@ # See the License for the specific language governing permissions and # limitations under the License. # require 'chef/knife' +require 'chef/knife/topo/loader' +require 'chef/knife/topo/consts' +require 'chef/knife/topo/command_helper' +require 'chef/knife/topo/consts' -require_relative 'topology_helper' +# NOTE: This command exports to stdout -# NOTE: This command exports to stdout +module KnifeTopo + # knife topo export + class TopoExport < Chef::Knife + deps do + end -class Chef - class Knife - class TopoExport < Chef::Knife + banner 'knife topo export [ NODE ... ] (options)' - deps do - end + option( + :data_bag, + short: '-D DATA_BAG', + long: '--data-bag DATA_BAG', + description: 'The data bag the topologies are stored in' + ) - banner "knife topo export [ TOPOLOGY [ NODE ... ]] (options)" + option( + :min_priority, + long: '--min-priority PRIORITY', + default: 'default', + description: 'Export attributes with this priority or above' + ) - option :data_bag, - :short => '-D DATA_BAG', - :long => "--data-bag DATA_BAG", - :description => "The data bag the topologies are stored in" - - option :min_priority, - :long => "--min-priority PRIORITY", - :default => "default", - :description => "Export attributes with this priority or above" - - option :topo, - :long => "--topo TOPOLOGY", - :description => "Name to use for the topology", - :default => "topo1" - - option :all, - :long => "--all", - :description => "Export all topologies", - :boolean => true, - :default => false + option( + :topo, + long: '--topo TOPOLOGY', + description: 'Name to use for the topology', + default: 'topo1' + ) - def most_common (vals) - vals.group_by do |val| - val - end.values.max_by(&:size).first + include KnifeTopo::Loader + include KnifeTopo::CommandHelper + + def run + unless KnifeTopo::PRIORITIES.include?(config[:min_priority]) + ui.warn('--min-priority should be one of ' \ + "#{KnifeTopo::PRIORITIES.join(', ')}") end - - def run + @topo_name = config[:topo] + @node_names = @name_args + output(Chef::JSONCompat.to_json_pretty(load_or_initialize_topo)) + end - @bag_name = topo_bag_name(config[:data_bag]) + def load_or_initialize_topo + topo = load_topo_from_server(@topo_name) + if topo + export = topo.raw_data + update_nodes!(export['nodes']) + else + export = new_topo + end + export + end - @topo_name = config[:topo] unless config[:all] - @node_names = @name_args - - unless ['default', 'normal', 'override'].include?(config[:min_priority]) - ui.warn("--min-priority should be one of 'default', 'normal' or 'override'") - end - - if @topo_name - if topo = load_from_server(@bag_name, @topo_name) - export = topo.raw_data - else - export = empty_topology - export['nodes'].push(empty_node("node1")) if @node_names.length == 0 - end + def new_topo + topo = empty_topology + update_nodes!(topo['nodes']) - # merge in data for nodes that user explicitly specified - @node_names.each do |node_name| - merge_node_properties!(export['nodes'], node_name) - end - - # if a new topo, pick an topo environment based on the nodes - if !topo && @node_names.length != 0 - envs = [] - export['nodes'].each do |node| - envs << node['chef_environment'] if node['chef_environment'] - end - export['chef_environment'] = most_common(envs) if envs.length > 0 - end + # pick an topo environment based on the nodes + return topo if @node_names.length == 0 + env = pick_env(topo['nodes']) + topo['chef_environment'] = env if env + topo + end - else - # export all topologies - export = [] - if dbag = load_from_server(@bag_name) - dbag.keys.each do |topo_name| - if topo = load_from_server(@bag_name, topo_name) - export << topo.raw_data - end - end - end - end - - output(Chef::JSONCompat.to_json_pretty(export)) + def pick_env(nodes) + envs = [] + nodes.each do |node| + envs << node['chef_environment'] if node['chef_environment'] end + most_common(envs) + end - # give user a template to get started - def empty_topology - { - "id" => @topo_name || "topo1", - "name" => @topo_name || "topo1", - "chef_environment" => "_default", - "tags" => [ ], - "nodes" => [ ], - "cookbook_attributes" => [{ - "cookbook" => @topo_name || "topo1", - "filename" => "topology" - }] - } - end + # give user a template to get started + def empty_topology + { + 'id' => @topo_name || 'topo1', + 'name' => @topo_name || 'topo1', + 'chef_environment' => '_default', + 'tags' => [], + 'strategy' => 'via_cookbook', + 'strategy_data' => default_strategy_data, + 'nodes' => @node_names.length == 0 ? [empty_node('node1')] : [] + } + end - def empty_node(name) - { - "name" => name, - "run_list" => [], - "ssh_host" => name, - "ssh_port" => "22", - "normal" => {}, - "tags" => [] - } - end + def default_strategy_data + { + 'cookbook' => @topo_name || 'topo1', + 'filename' => 'topology' + } + end - # get actual node properties for export - def node_export (node_name) + def empty_node(name) + { + 'name' => name, + 'run_list' => [], + 'ssh_host' => name, + 'ssh_port' => '22', + 'normal' => {}, + 'tags' => [] + } + end - node_data = {} + # get actual node properties for export + def node_export(node_name) + load_node_data(node_name, config[:min_priority]) + rescue Net::HTTPServerException => e + raise unless e.to_s =~ /^404/ + empty_node(node_name) + end - begin - node = Chef::Node.load(node_name) - - node_data['name'] = node.name - node_data['tags'] = node.tags - node_data['chef_environment'] = node.chef_environment - node_data['run_list'] = node.run_list - - pri = config[:min_priority] - node_data['default'] = node.default if pri == "default" - node_data['normal'] = node.normal if pri == "default" || pri == "normal" - node_data['override'] = node.override - - rescue Net::HTTPServerException => e - raise unless e.to_s =~ /^404/ - node_data = empty_node(node_name) - end - - node_data - end - - # merge hash properties with the actual node properties - def merge_node_properties!(nodes, node_name) + # put node details in node array, overwriting existing details + def update_nodes!(nodes) + @node_names.each do |node_name| # find out if the node is already in the array - found = nodes.index{|n| n["name"] == node_name } + found = nodes.index { |n| n['name'] == node_name } if found.nil? nodes.push(node_export(node_name)) else nodes[found] = node_export(node_name) end end - - include Chef::Knife::TopologyHelper - end end end