class MotherBrain::Bootstrap::Worker
@api private
Public Instance Methods
Perform a bootstrap on a group of nodes which have not yet been registered with the Chef
server and may not have Ruby, Chef
, or other requirements installed.
@example
host = Host.new("cloud-1.riotgames.com") worker.full_bootstrap(host) #=> { node_name: "cloud-1", hostname: "cloud-1.riotgames.com", status: :ok message: "", bootstrap_type: :full }
@param [Worker::Host] host
a host to bootstrap
@option options [String] :environment
environment to join the node to (default: '_default')
@option options [String] :chef_version
version of Chef to install on the node
@option options [Hash] :attributes (Hash.new)
a hash of attributes to use in the first Chef run
@option options [Array] :run_list (Array.new)
an initial run list to bootstrap with
@option options [Hash] :hints (Hash.new)
a hash of Ohai hints to place on the bootstrapped node
@option options [Boolean] :sudo (true)
bootstrap with sudo
@return [Hash]
# File lib/mb/bootstrap/worker.rb, line 134 def full_bootstrap(host, options = {}) options = options.reverse_merge( run_list: Array.new, attributes: Hash.new, hints: Hash.new, sudo: true ) begin options[:template] = MB::Bootstrap::Template.find(options[:template]) rescue MB::BootstrapTemplateNotFound => e abort e end options.delete(:template) if options[:template].nil? ssh_response = chef_connection.node.bootstrap(host.hostname, options) {}.tap do |response| response[:node_name] = nil response[:hostname] = ssh_response.host response[:bootstrap_type] = :full response[:message] = "" response[:status] = :ok if ssh_response.error? response[:status] = :error response[:message] = ssh_response.stderr.chomp end end end
Perform a bootstrap on a group of nodes which have already been registered with the Chef
server.
Partial bootstrap steps:
1. The given values given for the run_list and attributes options will be merged with the existing node data 2. Your organization's secret key will be placed on the node 3. Perform a chef client run on the target node
@example
host = Host.new("cloud-1.riotgames.com") worker.partial_bootstrap(host) #=> { node_name: "cloud-1", hostname: "cloud-1.riotgames.com", status: :ok message: "", bootstrap_type: :partial }
@param [Worker::Host] host
a host to bootstrap
@option options [Array] :run_list
a chef run list
@option options [Hash] :attributes
attributes to set on the node at normal precedence
@return [Hash]
# File lib/mb/bootstrap/worker.rb, line 192 def partial_bootstrap(host, options = {}) log.info "#{host} is already registered with Chef. Performing a partial bootstrap." {}.tap do |response| response[:node_name] = host.node_name response[:hostname] = host.hostname response[:bootstrap_type] = :partial response[:message] = "" response[:status] = :ok begin chef_connection.node.merge_data(host.node_name, options.slice(:run_list, :attributes)) node_querier.put_secret(host.hostname) node_querier.chef_run(host.hostname) rescue Ridley::Errors::ResourceNotFound => ex response[:status] = :error response[:message] = "Host #{host} has a client on the node and a matching client on the Chef server, " + "but there is no matching node object on the Chef server for the client. This should not happen. " + "Run `mb purge #{host}` or manually destroy the client on the node itself and the node object on " + "the Chef server and re-run your bootstrap." # JW TODO: We can recover here by creating the node object. However, we can't do this right # now because OHC/OPC have ACLs associated with the node object. When we create the object the # API user that we are acting as will be the only user with full permissions to the node # object resulting in a 403 error when the node attempts to save itself back to the Chef server. # # TLDR; The undocumented ACL endpoints need to be implemented in Ridley to support graceful # recovery. https://github.com/RiotGames/ridley/issues/147 rescue Exception => ex response[:status] = :error response[:message] = ex.to_s end end end
Run a bootstrap on each of the hosts given to this instance of {Worker}. There are two different kinds of bootstrap processes which may be run on a node; a partial bootstrap and a full bootstrap.
Partial Bootstrap: a node will be partially bootstrapped if it has
1. Chef installed by omnibus 2. Ruby installed by omnibus 3. A Chef client registered with the Chef server. note: the name of the client is the "node_name" of the node. This obtained by running the ruby node name script "script/node_name.rb" on the node.
Full Bootstrap: a node will be fully bootstrapped if it does not satisfy all of the criteria for a
partial bootstrap.
@example
worker = Worker.new worker.run("cloud-1.riotgames.com") #=> { node: "cloud-1.riotgames.com", status: :ok, message: "", bootstrap_type: :full }
@param [String] address
a hostname or ipaddress to bootstrap
@option options [String] :environment
environment to join the node to (default: '_default')
@option options [Hash] :attributes (Hash.new)
a hash of attributes to use in the first Chef run
@option options [Array] :run_list (Array.new)
an initial run list to bootstrap with
@option options [String] :chef_version
version of Chef to install on the node
@option options [Hash] :hints (Hash.new)
a hash of Ohai hints to place on the bootstrapped node
@option options [Boolean] :sudo (true)
bootstrap with sudo
@option options [String] :bootstrap_proxy (nil)
URL to a proxy server to bootstrap through
@return [Hash]
# File lib/mb/bootstrap/worker.rb, line 94 def run(address, options = {}) host = Host.new(address) if host.full_bootstrap? full_bootstrap(host, options) else partial_bootstrap(host, options.slice(:attributes, :run_list)) end end