class Chef::Knife::Bootstrap

Attributes

chef_vault_handler[RW]
client_builder[RW]

Public Class Methods

new(argv = []) click to toggle source
Calls superclass method
# File lib/chef/knife/bootstrap.rb, line 253
def initialize(argv = [])
  super
  @client_builder = Chef::Knife::Bootstrap::ClientBuilder.new(
    chef_config: Chef::Config,
    knife_config: config,
    ui: ui
  )
  @chef_vault_handler = Chef::Knife::Bootstrap::ChefVaultHandler.new(
    knife_config: config,
    ui: ui
  )
end

Public Instance Methods

bootstrap_context() click to toggle source
# File lib/chef/knife/bootstrap.rb, line 337
def bootstrap_context
  @bootstrap_context ||= Knife::Core::BootstrapContext.new(
    config,
    config[:run_list],
    Chef::Config,
    secret
  )
end
bootstrap_template() click to toggle source
# File lib/chef/knife/bootstrap.rb, line 295
def bootstrap_template
  # Allow passing a bootstrap template or use the default
  # @return [String] The CLI specific bootstrap template or the default
  config[:bootstrap_template] || default_bootstrap_template
end
default_bootstrap_template() click to toggle source

The default bootstrap template to use to bootstrap a server This is a public API hook which knife plugins use or inherit and override.

@return [String] Default bootstrap template

# File lib/chef/knife/bootstrap.rb, line 270
def default_bootstrap_template
  "chef-full"
end
find_template() click to toggle source
# File lib/chef/knife/bootstrap.rb, line 301
def find_template
  template = bootstrap_template

  # Use the template directly if it's a path to an actual file
  if File.exists?(template)
    Chef::Log.trace("Using the specified bootstrap template: #{File.dirname(template)}")
    return template
  end

  # Otherwise search the template directories until we find the right one
  bootstrap_files = []
  bootstrap_files << File.join(File.dirname(__FILE__), "bootstrap/templates", "#{template}.erb")
  bootstrap_files << File.join(Knife.chef_config_dir, "bootstrap", "#{template}.erb") if Chef::Knife.chef_config_dir
  Chef::Util::PathHelper.home(".chef", "bootstrap", "#{template}.erb") { |p| bootstrap_files << p }
  bootstrap_files << Gem.find_files(File.join("chef", "knife", "bootstrap", "#{template}.erb"))
  bootstrap_files.flatten!

  template_file = Array(bootstrap_files).find do |bootstrap_template|
    Chef::Log.trace("Looking for bootstrap template in #{File.dirname(bootstrap_template)}")
    File.exists?(bootstrap_template)
  end

  unless template_file
    ui.info("Can not find bootstrap definition for #{template}")
    raise Errno::ENOENT
  end

  Chef::Log.trace("Found bootstrap template in #{File.dirname(template_file)}")

  template_file
end
first_boot_attributes() click to toggle source
# File lib/chef/knife/bootstrap.rb, line 346
def first_boot_attributes
  @config[:first_boot_attributes] || @config[:first_boot_attributes_from_file] || {}
end
host_descriptor() click to toggle source
# File lib/chef/knife/bootstrap.rb, line 274
def host_descriptor
  Array(@name_args).first
end
knife_ssh() click to toggle source
# File lib/chef/knife/bootstrap.rb, line 423
def knife_ssh
  ssh = Chef::Knife::Ssh.new
  ssh.ui = ui
  ssh.name_args = [ server_name, ssh_command ]
  ssh.config[:ssh_user] = user_name || config[:ssh_user]
  ssh.config[:ssh_password] = config[:ssh_password]
  ssh.config[:ssh_port] = config[:ssh_port]
  ssh.config[:ssh_gateway] = config[:ssh_gateway]
  ssh.config[:ssh_gateway_identity] = config[:ssh_gateway_identity]
  ssh.config[:forward_agent] = config[:forward_agent]
  ssh.config[:ssh_identity_file] = config[:ssh_identity_file] || config[:identity_file]
  ssh.config[:manual] = true
  ssh.config[:host_key_verify] = config[:host_key_verify]
  ssh.config[:on_error] = true
  ssh
end
knife_ssh_with_password_auth() click to toggle source
# File lib/chef/knife/bootstrap.rb, line 440
def knife_ssh_with_password_auth
  ssh = knife_ssh
  ssh.config[:ssh_identity_file] = nil
  ssh.config[:ssh_password] = ssh.get_password
  ssh
end
render_template() click to toggle source
# File lib/chef/knife/bootstrap.rb, line 350
def render_template
  @config[:first_boot_attributes] = first_boot_attributes
  template_file = find_template
  template = IO.read(template_file).chomp
  Erubis::Eruby.new(template).evaluate(bootstrap_context)
end
run() click to toggle source
# File lib/chef/knife/bootstrap.rb, line 357
def run
  if @config[:first_boot_attributes] && @config[:first_boot_attributes_from_file]
    raise Chef::Exceptions::BootstrapCommandInputError
  end

  validate_name_args!
  validate_options!

  $stdout.sync = true

  # chef-vault integration must use the new client-side hawtness, otherwise to use the
  # new client-side hawtness, just delete your validation key.
  if chef_vault_handler.doing_chef_vault? ||
      (Chef::Config[:validation_key] && !File.exist?(File.expand_path(Chef::Config[:validation_key])))

    unless config[:chef_node_name]
      ui.error("You must pass a node name with -N when bootstrapping with user credentials")
      exit 1
    end

    client_builder.run

    chef_vault_handler.run(client_builder.client)

    bootstrap_context.client_pem = client_builder.client_path
  else
    ui.info("Doing old-style registration with the validation key at #{Chef::Config[:validation_key]}...")
    ui.info("Delete your validation key in order to use your user credentials instead")
    ui.info("")
  end

  ui.info("Connecting to #{ui.color(server_name, :bold)}")

  begin
    knife_ssh.run
  rescue Net::SSH::AuthenticationFailed
    if config[:ssh_password]
      raise
    else
      ui.info("Failed to authenticate #{knife_ssh.config[:ssh_user]} - trying password auth")
      knife_ssh_with_password_auth.run
    end
  end
end
secret() click to toggle source
# File lib/chef/knife/bootstrap.rb, line 333
def secret
  @secret ||= encryption_secret_provided_ignore_encrypt_flag? ? read_secret : nil
end
server_name() click to toggle source

The #server_name is the DNS or IP we are going to connect to, it is not necessarily the node name, the fqdn, or the hostname of the server. This is a public API hook which knife plugins use or inherit and override.

@return [String] The DNS or IP that bootstrap will connect to

# File lib/chef/knife/bootstrap.rb, line 283
def server_name
  if host_descriptor
    @server_name ||= host_descriptor.split("@").reverse[0]
  end
end
ssh_command() click to toggle source
# File lib/chef/knife/bootstrap.rb, line 447
def ssh_command
  command = render_template

  if config[:use_sudo]
    sudo_prefix = config[:use_sudo_password] ? "echo '#{config[:ssh_password]}' | sudo -S " : "sudo "
    command = config[:preserve_home] ? "#{sudo_prefix} #{command}" : "#{sudo_prefix} -H #{command}"
  end

  command
end
user_name() click to toggle source
# File lib/chef/knife/bootstrap.rb, line 289
def user_name
  if host_descriptor
    @user_name ||= host_descriptor.split("@").reverse[1]
  end
end
validate_name_args!() click to toggle source
# File lib/chef/knife/bootstrap.rb, line 402
def validate_name_args!
  if server_name.nil?
    ui.error("Must pass an FQDN or ip to bootstrap")
    exit 1
  elsif server_name == "windows"
    # catches "knife bootstrap windows" when that command is not installed
    ui.warn("Hostname containing 'windows' specified. Please install 'knife-windows' if you are attempting to bootstrap a Windows node via WinRM.")
  end
end
validate_options!() click to toggle source
# File lib/chef/knife/bootstrap.rb, line 412
def validate_options!
  if incomplete_policyfile_options?
    ui.error("--policy-name and --policy-group must be specified together")
    exit 1
  elsif policyfile_and_run_list_given?
    ui.error("Policyfile options and --run-list are exclusive")
    exit 1
  end
  true
end

Private Instance Methods

incomplete_policyfile_options?() click to toggle source

True if one of policy_name or policy_group was given, but not both

# File lib/chef/knife/bootstrap.rb, line 474
def incomplete_policyfile_options?
  (!!config[:policy_name] ^ config[:policy_group])
end
policyfile_and_run_list_given?() click to toggle source

True if policy_name and run_list are both given

# File lib/chef/knife/bootstrap.rb, line 461
def policyfile_and_run_list_given?
  run_list_given? && policyfile_options_given?
end
policyfile_options_given?() click to toggle source
# File lib/chef/knife/bootstrap.rb, line 469
def policyfile_options_given?
  !!config[:policy_name]
end
run_list_given?() click to toggle source
# File lib/chef/knife/bootstrap.rb, line 465
def run_list_given?
  !config[:run_list].nil? && !config[:run_list].empty?
end