class Chef::Knife::Bootstrap::ClientBuilder

def chef_server_url

Returns:
  • (String) - chef server url from the Chef::Config
def chef_server_url
  chef_config[:chef_server_url]
end

def client_path

Returns:
  • (String) - path to the generated client.pem
def client_path
  @client_path ||=
    begin
      @tmpdir = Dir.mktmpdir
      File.join(@tmpdir, "#{node_name}.pem")
    end
end

def client_rest

Returns:
  • (Chef::ServerAPI) - REST client using the client credentials
def client_rest
  @client_rest ||= Chef::ServerAPI.new(chef_server_url, client_name: node_name, signing_key_filename: client_path)
end

def create_client!

Create the client object and save it to the Chef API
def create_client!
  Chef::ApiClient::Registration.new(node_name, client_path, http_api: rest).run
end

def create_node!

Create the node object (via the lazy accessor) and save it to the Chef API
def create_node!
  node.save
end

def environment

Returns:
  • (String) - environment from the config
def environment
  config[:environment]
end

def first_boot_attributes

Returns:
  • (Hash, Array) - Object representation of json first-boot attributes from the config
def first_boot_attributes
  config[:first_boot_attributes]
end

def initialize(config: {}, knife_config: nil, chef_config: {}, ui: nil)

Parameters:
  • ui (Chef::Knife::UI) -- UI object for output
  • chef_config (Hash) -- Hash of chef config settings
  • config (Hash) -- Hash of knife config settings
def initialize(config: {}, knife_config: nil, chef_config: {}, ui: nil)
  @config = config
  unless knife_config.nil?
    @config = knife_config
    Chef.deprecated(:knife_bootstrap_apis, "The knife_config option to the Bootstrap::ClientBuilder object is deprecated and has been renamed to just 'config'")
  end
  @chef_config = chef_config
  @ui = ui
end

def node

Returns:
  • (Chef::Node) - new chef node to create
def node
  @node ||=
    begin
      node = Chef::Node.new(chef_server_rest: client_rest)
      node.name(node_name)
      node.run_list(normalized_run_list)
      node.normal_attrs = first_boot_attributes if first_boot_attributes
      node.environment(environment) if environment
      node.policy_name = policy_name if policy_name
      node.policy_group = policy_group if policy_group
      (config[:tags] || []).each do |tag|
        node.tags << tag
      end
      node
    end
end

def node_name

Returns:
  • (String) - node name from the config
def node_name
  config[:chef_node_name]
end

def normalized_run_list

Returns:
  • (Array) - run_list coerced into an array
def normalized_run_list
  case run_list
  when nil
    []
  when String
    run_list.split(/\s*,\s*/)
  when Array
    run_list
  end
end

def policy_group

Returns:
  • (String) - policy_group from the config
def policy_group
  config[:policy_group]
end

def policy_name

Returns:
  • (String) - policy_name from the config
def policy_name
  config[:policy_name]
end

def resource_exists?(relative_path)

Returns:
  • (Boolean) - if the relative path exists or returns a 404

Parameters:
  • relative_path (String) -- URI path relative to the chef organization
def resource_exists?(relative_path)
  rest.get(relative_path)
  true
rescue Net::HTTPClientException => e
  raise unless e.response.code == "404"
  false
end

def rest

Returns:
  • (Chef::ServerAPI) - REST client using the cli user's knife credentials
def rest
  @rest ||= Chef::ServerAPI.new(chef_server_url)
end

def run

the new client, then create the new node.
Main entry. Prompt the user to clean up any old client or node objects. Then create
def run
  sanity_check
  ui.info("Creating new client for #{node_name}")
  @client = create_client!
  ui.info("Creating new node for #{node_name}")
  create_node!
end

def run_list

Returns:
  • (String) - run_list from the config
def run_list
  config[:run_list]
end

def sanity_check

delete any prior node/client objects.
We prompt the user about what to do and will fail hard if we do not get confirmation to

client and wiring it up to a precreated node object, but we do currently support that.
object with the permissions of the new client. There is a use case for creating a new
already exists, we must delete it in order to proceed so that we can create a new node
Check for the existence of a node and/or client already on the server. If the node
def sanity_check
  if resource_exists?("nodes/#{node_name}")
    ui.confirm("Node #{node_name} exists, overwrite it")
    rest.delete("nodes/#{node_name}")
  end
  if resource_exists?("clients/#{node_name}")
    ui.confirm("Client #{node_name} exists, overwrite it")
    rest.delete("clients/#{node_name}")
  end
end