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