summaryrefslogtreecommitdiff
path: root/lib/chef/knife/bootstrap.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chef/knife/bootstrap.rb')
-rw-r--r--lib/chef/knife/bootstrap.rb99
1 files changed, 84 insertions, 15 deletions
diff --git a/lib/chef/knife/bootstrap.rb b/lib/chef/knife/bootstrap.rb
index 19a329199d..f23c15fa70 100644
--- a/lib/chef/knife/bootstrap.rb
+++ b/lib/chef/knife/bootstrap.rb
@@ -19,12 +19,17 @@
require 'chef/knife'
require 'chef/knife/data_bag_secret_options'
require 'erubis'
+require 'chef/knife/bootstrap/chef_vault_handler'
+require 'chef/knife/bootstrap/client_builder'
class Chef
class Knife
class Bootstrap < Knife
include DataBagSecretOptions
+ attr_accessor :client_builder
+ attr_accessor :chef_vault_handler
+
deps do
require 'chef/knife/core/bootstrap_context'
require 'chef/json_compat'
@@ -194,10 +199,55 @@ class Chef
:description => "Verify the SSL cert for HTTPS requests to the Chef server API.",
:boolean => true
+ option :bootstrap_vault_file,
+ :long => '--bootstrap-vault-file VAULT_FILE',
+ :description => 'A JSON file with a list of vault(s) and item(s) to be updated'
+
+ option :bootstrap_vault_json,
+ :long => '--bootstrap-vault-json VAULT_JSON',
+ :description => 'A JSON string with the vault(s) and item(s) to be updated'
+
+ option :bootstrap_vault_item,
+ :long => '--bootstrap-vault-item VAULT_ITEM',
+ :description => 'A single vault and item to update as "vault:item"',
+ :proc => Proc.new { |i|
+ (vault, item) = i.split(/:/)
+ Chef::Config[:knife][:bootstrap_vault_item] ||= {}
+ Chef::Config[:knife][:bootstrap_vault_item][vault] ||= []
+ Chef::Config[:knife][:bootstrap_vault_item][vault].push(item)
+ Chef::Config[:knife][:bootstrap_vault_item]
+ }
+
+ 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
+
+ # 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
def default_bootstrap_template
"chef-full"
end
+ # 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
+ def server_name
+ Array(@name_args).first
+ end
+
def bootstrap_template
# The order here is important. We want to check if we have the new Chef 12 option is set first.
# Knife cloud plugins unfortunately all set a default option for the :distro so it should be at
@@ -216,7 +266,7 @@ class Chef
# Otherwise search the template directories until we find the right one
bootstrap_files = []
- bootstrap_files << File.join(File.dirname(__FILE__), 'bootstrap', "#{template}.erb")
+ 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
bootstrap_files << File.join(ENV['HOME'], '.chef', 'bootstrap', "#{template}.erb") if ENV['HOME']
bootstrap_files << Gem.find_files(File.join("chef","knife","bootstrap","#{template}.erb"))
@@ -237,20 +287,45 @@ class Chef
template_file
end
+ def secret
+ @secret ||= encryption_secret_provided_ignore_encrypt_flag? ? read_secret : nil
+ end
+
+ def bootstrap_context
+ @bootstrap_context ||= Knife::Core::BootstrapContext.new(
+ config,
+ config[:run_list],
+ Chef::Config,
+ secret
+ )
+ end
+
def render_template
template_file = find_template
template = IO.read(template_file).chomp
- secret = encryption_secret_provided_ignore_encrypt_flag? ? read_secret : nil
- context = Knife::Core::BootstrapContext.new(config, config[:run_list], Chef::Config, secret)
- Erubis::Eruby.new(template).evaluate(context)
+ Erubis::Eruby.new(template).evaluate(bootstrap_context)
end
def run
validate_name_args!
- @node_name = Array(@name_args).first
$stdout.sync = true
- ui.info("Connecting to #{ui.color(@node_name, :bold)}")
+
+ # 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? || !File.exist?(File.expand_path(Chef::Config[:validation_key]))
+ client_builder.run
+
+ chef_vault_handler.run(node_name: config[:chef_node_name])
+
+ 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
@@ -265,24 +340,19 @@ class Chef
end
def validate_name_args!
- if Array(@name_args).first.nil?
+ if server_name.nil?
ui.error("Must pass an FQDN or ip to bootstrap")
exit 1
- elsif Array(@name_args).first == "windows"
+ 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
- def server_name
- Array(@name_args).first
- end
-
def knife_ssh
ssh = Chef::Knife::Ssh.new
ssh.ui = ui
ssh.name_args = [ server_name, ssh_command ]
-
- # command line arguments and config file values are now merged into config in Chef::Knife#merge_configs
ssh.config[:ssh_user] = config[:ssh_user]
ssh.config[:ssh_password] = config[:ssh_password]
ssh.config[:ssh_port] = config[:ssh_port]
@@ -311,7 +381,6 @@ class Chef
command
end
-
end
end
end