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

- old
+ new

@@ -14,101 +14,129 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # - -require_relative 'topology_helper' +require 'chef/knife/topo/bootstrap_helper' +require 'chef/knife/topo/loader' require 'chef/knife/bootstrap' -class Chef - class Knife - class TopoBootstrap < Chef::Knife +module KnifeTopo + # knife topo bootstrap + class TopoBootstrap < Chef::Knife + deps do + require 'chef/knife/topo/processor' + end - deps do - Chef::Knife::Bootstrap.load_deps - end + include KnifeTopo::BootstrapHelper + include KnifeTopo::Loader - banner "knife topo bootstrap TOPOLOGY (options)" + banner 'knife topo bootstrap TOPOLOGY (options)' - option :data_bag, - :short => '-D DATA_BAG', - :long => "--data-bag DATA_BAG", - :description => "The data bag the topologies are stored in" - - option :overwrite, - :long => "--overwrite", - :description => "Whether to overwrite existing nodes", - :boolean => true + option( + :data_bag, + short: '-D DATA_BAG', + long: '--data-bag DATA_BAG', + description: 'The data bag the topologies are stored in' + ) - # Make the base bootstrap options available on topo bootstrap - self.options = (Chef::Knife::Bootstrap.options).merge(self.options) + option( + :overwrite, + long: '--overwrite', + description: 'Whether to overwrite existing nodes', + boolean: true + ) - def initialize (args) - super - @bootstrap_args = initialize_cmd_args(args, [ 'bootstrap', '' ]) + # Make the base bootstrap options available on topo bootstrap + self.options = (Chef::Knife::Bootstrap.options).merge(TopoBootstrap.options) - # All called commands need to accept union of options - Chef::Knife::Bootstrap.options = options + attr_accessor :msgs, :results - end + def bootstrap_msgs + { + bootstrapped: 'Bootstrapped %{num} nodes [ %{list} ]', + skipped: 'Unexpected error', + skipped_ssh: 'Did not bootstrap %{num} nodes [ %{list} ] ' \ + 'because they do not have an ssh_host', + existed: 'Did not bootstrap %{num} nodes [ %{list} ] because '\ + "they already exist.\n"\ + "Specify --overwrite to re-bootstrap existing nodes. \n", + failed: '%{num} nodes [ %{list} ] failed to bootstrap due to errors' + } + end - def run - if !@name_args[0] - show_usage - ui.fatal("You must specify the name of a topology") - exit 1 - end + def initialize(args) + super + @bootstrap_args = initialize_cmd_args(args, name_args, ['bootstrap', '']) + @results = { + bootstrapped: [], skipped: [], skipped_ssh: [], existed: [], failed: [] + } + @msgs = bootstrap_msgs + @bootstrap = true - @bag_name = topo_bag_name(config[:data_bag]) - @topo_name = @name_args[0] + # All called commands need to accept union of options + Chef::Knife::Bootstrap.options = options + end - # get the node names for the topology - unless topo = load_from_server(@bag_name, @topo_name ) - ui.fatal("Topology #{@bag_name}/#{@topo_name} does not exist on the server - use 'knife topo create' first") - exit(1) - end + def run + validate_args - # load and bootstrap each node that has a ssh_host - nodes = merge_topo_properties(topo['nodes'], topo) - - bootstrapped = [] - skipped = [] - existed = [] - failed = [] - - if nodes.length > 0 - nodes.each do |node_data| - node_name = node_data['name'] - exists = resource_exists?("nodes/#{node_name}") - if(node_data['ssh_host'] && (config[:overwrite] || !exists)) - if run_bootstrap(node_data, @bootstrap_args, exists) - bootstrapped << node_name - else - failed << node_name - end - else - if(exists) - existed << node_name - else - skipped << node_name - end - end - end - ui.info("Bootstrapped #{bootstrapped.length} nodes [ #{bootstrapped.join(', ')} ]") - ui.info("Skipped #{skipped.length} nodes [ #{skipped.join(', ')} ] because they had no ssh_host information") if skipped.length > 0 - if existed.length > 0 - ui.info("Skipped #{existed.length} nodes [ #{existed.join(', ')} ] because they already exist. " + - "Specify --overwrite to re-bootstrap existing nodes. " + - "If you are using Chef Vault, you may need to use --bootstrap-vault options in this case.") - end - ui.warn("#{failed.length} nodes [ #{failed.join(', ')} ] failed to bootstrap due to errors") if failed.length > 0 + # load and bootstrap each node that has a ssh_host + @topo = load_topo_from_server_or_exit(@topo_name) + @processor = KnifeTopo::Processor.for_topo(@topo) + nodes = @processor.generate_nodes + nodes.each do |node_data| + node_bootstrap(node_data) + end + + report + end + + def validate_args + unless @name_args[0] + show_usage + ui.fatal('You must specify the name of a topology') + exit 1 + end + @topo_name = @name_args[0] + end + + # rubocop:disable Metrics/MethodLength + def node_bootstrap(node_data) + node_name = node_data['name'] + state = :skipped_ssh + if node_data['ssh_host'] + exists = resource_exists?("nodes/#{node_name}") + if config[:overwrite] || !exists + success = run_bootstrap(node_data, @bootstrap_args, exists) + state = success ? :bootstrapped : :failed else - ui.info "No nodes found for topology #{display_name(topo)}" + state = :existed end end + @results[state] << node_name + success + end + # rubocop:enable Metrics/MethodLength - include Chef::Knife::TopologyHelper + # Report is used by create, update and bootstrap commands + def report + if @topo['nodes'].length > 0 + report_msg(:bootstrapped, :info, false) if @bootstrap + report_msg(:skipped, :info, true) + report_msg(:skipped_ssh, :info, true) + report_msg(:existed, :info, true) + report_msg(:failed, :warn, true) if @bootstrap + else + ui.info 'No nodes found' + end + ui.info("Topology: #{@topo.display_info}") + end + def report_msg(state, level, only_non_zero = true) + nodes = @results[state] + return if only_non_zero && nodes.length == 0 + ui.send(level, @msgs[state] % + { num: nodes.length, list: nodes.join(', ') }) end end end