Class: MotherBrain::Bootstrap::Worker Private

Inherits:
Object
  • Object
show all
Includes:
Celluloid, MB::Mixin::Services, Logging
Defined in:
lib/mb/bootstrap/worker.rb

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Defined Under Namespace

Classes: Host

Instance Method Summary collapse

Methods included from Logging

add_argument_header, dev, filename, #log_exception, logger, #logger, reset, set_logger, setup

Instance Method Details

#full_bootstrap(host, options = {}) ⇒ Hash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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.

Examples:

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
}

Parameters:

  • host (Worker::Host)

    a host to bootstrap

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :environment (String)

    environment to join the node to (default: ‘_default’)

  • :chef_version (String)

    version of Chef to install on the node

  • :attributes (Hash) — default: Hash.new

    a hash of attributes to use in the first Chef run

  • :run_list (Array) — default: Array.new

    an initial run list to bootstrap with

  • :hints (Hash) — default: Hash.new

    a hash of Ohai hints to place on the bootstrapped node

  • :sudo (Boolean) — default: true

    bootstrap with sudo

Returns:

  • (Hash)


134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# 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

#partial_bootstrap(host, options = {}) ⇒ Hash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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

Examples:

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
}

Parameters:

  • host (Worker::Host)

    a host to bootstrap

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :run_list (Array)

    a chef run list

  • :attributes (Hash)

    attributes to set on the node at normal precedence

Returns:

  • (Hash)


192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# 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(address, options = {}) ⇒ Hash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Run a bootstrap on each of the hosts given to this instance of MotherBrain::Bootstrap::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.

Examples:

worker = Worker.new
worker.run("cloud-1.riotgames.com") #=> {
  node: "cloud-1.riotgames.com",
  status: :ok,
  message: "",
  bootstrap_type: :full
}

Parameters:

  • address (String)

    a hostname or ipaddress to bootstrap

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :environment (String)

    environment to join the node to (default: ‘_default’)

  • :attributes (Hash) — default: Hash.new

    a hash of attributes to use in the first Chef run

  • :run_list (Array) — default: Array.new

    an initial run list to bootstrap with

  • :chef_version (String)

    version of Chef to install on the node

  • :hints (Hash) — default: Hash.new

    a hash of Ohai hints to place on the bootstrapped node

  • :sudo (Boolean) — default: true

    bootstrap with sudo

  • :bootstrap_proxy (String) — default: nil

    URL to a proxy server to bootstrap through

Returns:

  • (Hash)


94
95
96
97
98
99
100
101
# 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