lib/chef/knife/server_bootstrap_base.rb
# -*- encoding: utf-8 -*-
#
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
# Copyright:: Copyright (c) 2012 Fletcher Nichol
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# 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 "chef/knife"
class Chef
class Knife
# Common behavior for server bootstrapping.
module ServerBootstrapBase
def self.included(included_class) # rubocop:disable Metrics/MethodLength
included_class.class_eval do
deps do
require "chef/knife/ssh"
require "net/ssh"
end
option :platform,
:short => "-P PLATFORM",
:long => "--platform PLATFORM",
:description => "The platform type that will be bootstrapped, "\
"default is 'omnibus'",
:default => "omnibus"
option :distro,
:short => "-d DISTRO",
:long => "--distro DISTRO",
:description => "Bootstrap a distro using a template, " \
"default is 'chef11/omnibus'"
option :bootstrap_version,
:long => "--bootstrap-version VERSION",
:description => "The version of Chef Server to install, " \
"default is latest release",
:proc => proc { |v| Chef::Config[:knife][:bootstrap_version] = v },
:default => nil
option :prerelease,
:long => "--prerelease",
:description => "Install a pre-release version of Chef Server"
option :webui_enable,
:long => "--[no-]webui-enable",
:description => "Whether or not to enable the webui, " \
"default is false",
:proc => proc { |v| Chef::Config[:knife][:webui_enable] = v },
:default => false
option :webui_password,
:long => "--webui-password SECRET",
:description => "Initial password for WebUI admin account, " \
"default is 'chefchef'",
:default => "chefchef"
option :amqp_password,
:long => "--amqp-password SECRET",
:description => "Initial password for AMQP, default is 'chefchef'",
:default => "chefchef"
option :log_level,
:short => "-l LEVEL",
:long => "--log-level LEVEL",
:description => "Set the log level " \
"(debug, info, warn, error, fatal), default is error",
:proc => proc { |v| Chef::Config[:knife][:log_level] = v.to_sym },
:default => :error
option :no_test,
:short => "-n",
:long => "--no-test",
:description => "Do not run opscode pedant as a part of the " \
"omnibus installation"
option :url,
:long => "--url URL",
:description => "URL to specfic package release",
:proc => proc { |u| Chef::Config[:knife][:server_package_url] = u }
end
end
def run
validate!
end
private
def validate!
knife_fail = "You did not set {{KEY}} in your knife.rb, which is a " \
"required setting. Please generate an initial knife.rb or read " \
"the setup instructions at http://fnichol.github.io/knife-server/"
# rubocop:disable Style/DeprecatedHashMethods
if Chef::Config[:node_name].nil?
ui.error knife_fail.gsub(/{{KEY}}/, "node_name")
exit 1
end
if Chef::Config[:client_key].nil?
ui.error knife_fail.gsub(/{{KEY}}/, "client_key")
exit 1
end
# rubocop:enable Style/DeprecatedHashMethods
end
def fetch_validation_key
credentials_client.install_validation_key
end
def install_client_key
credentials_client.install_client_key(
Chef::Config[:node_name], Chef::Config[:client_key])
end
def create_root_client
ui.msg(credentials_client.create_root_client)
end
def bootstrap_auto?
config_val(:platform) == "auto"
end
def distro_auto_map(platform, _platform_version)
# NOTE this logic is shared with chef/knife/bootstrap/auto.sh, which is
# run on the server side.
# XXX we don't actually use the platform_version stuff, just included
# because we get it for free in the script and it might prove
# useful later.
# XXX might be better to have chef/ohai's platform_family? do this for
# us in the long term.
normal = case platform
when "debian", "ubuntu"
"debian"
when "el", "redhat"
"rhel"
when /^solaris/
"solaris"
when "sles", "suse"
"suse"
end
construct_distro(normal)
end
def construct_distro(platform)
"chef#{chef_server_major_version}/#{platform}"
end
def chef_server_major_version
version = config_val(:bootstrap_version)
version.nil? ? 11 : version.split(".").first.to_i
end
def bootstrap_distro
return config_val(:distro) if config_val(:distro)
return determine_platform if config_val(:platform) == "auto"
construct_distro(config_val(:platform))
end
def credentials_client
opts = {}
opts[:omnibus] = true if chef_server_major_version > 10
@credentials_client ||= ::Knife::Server::Credentials.new(
ssh_connection, Chef::Config[:validation_key], opts)
end
def determine_platform
return nil unless bootstrap_auto?
script = File.binread(
File.expand_path("bootstrap/auto.sh", File.dirname(__FILE__))
)
# result is expected to be two lines, first being the platform name,
# second being the platform version.
result, exit_status = ssh_connection.run_script(script)
if exit_status != 0 || !result || result.strip.empty?
raise "Could not determine the OS running the target for " \
"the chef server. Please specify --platform."
end
distro_auto_map(*result.split(/\n/).compact[0..1])
end
def config_val(key)
key = key.to_sym
case
when !config[key].nil?
config[key]
when !Chef::Config[:knife][key].nil?
Chef::Config[:knife][key]
else
options[key] && options[key][:default]
end
end
end
end
end