double-z
8/8/2015 - 8:23 AM

chef-provisioning cluster provider

chef-provisioning cluster provider

use_inline_resources

require 'json'

include ClcLibrary::Helper
include Provisioner::Helper

def whyrun_supported?
  true
end

action :create do
  cluster_resource = @new_resource
  hypervisor, hypervisor_type = hypervisor_for(
    cluster_resource,
    stamp_for(current_stamp)['hypervisors']
  )

  secrets = provisioner_secrets(cluster_resource)
  set_vsphere_auth_context(secrets, hypervisor, hypervisor_type)
  set_chef_server_context(cluster_resource)

  # This attribute is currently set in .kitchen.yml.
  # Better to pass as attribute to stamp.rb recipe?
  # with_chef_environment node.provisioner.environment
  with_chef_environment node.chef_environment

  machine_options = machine_options_for(
    cluster_resource,
    hypervisor,
    hypervisor_type,
    current_network,
    secrets
  )

  updated = true
  idx = cluster_resource.skip
  setup = machine_batch do
    machine_options.keys.each do |machine_name|
      # Spin up machine, install chef-client and create client/node objects, but don't converge.
      machine machine_name do
        machine_options machine_options[machine_name]
        attributes attributes_for(machine_name, cluster_resource)
        run_list run_list_for(cluster_resource, idx)
        complete true  # Windows cluster test fails if this is set to false
        converge false
        action :setup  # chef docs and metal github doc disagree on actions.  tried first with :create, per docs, not happy
      end
      idx += 1
    end
    action :setup
  end

  if !cluster_resource.converge && !setup.updated_by_last_action?
    updated = false
  end

  # Wait to make sure last machine created exists.  This is stoopid, but vault refresh has been failing
  # due to latency on clients being searchable.  Have seen latency of more than a minute on 1/27.  Argh.
  ruby_block "killing_time" do
    block do
      with_chef_server(
      cluster_resource.chef_server_url,
      cluster_resource.chef_server_user,
      cluster_resource.chef_server_key
      ) do
        last_machine = machine_options.keys.last
        retries = 0
        last_client = search(:client, "name:#{last_machine}")
        until ( last_client.count > 0 || retries >= 24 ) do
          Chef::Log.info "**** Waiting for #{last_machine} client to be searchable. ****"
          retries = retries + 1
          sleep 5
          last_client = search(:client, "name:#{last_machine}")
        end
        if last_client.count == 0
          raise "Cannot find client object for #{last_machine}!  Exiting."
        end
      end
    end
  end

  # Refresh relevant vault item -- i.e. have search run again -- so that key for new node is added to item_keys
  # Assumes: Vault exists and is encrypted to client used in the refresh command
  ruby_block "refresh_vault" do
    block do
      with_chef_server(
        cluster_resource.chef_server_url,
        cluster_resource.chef_server_user,
        cluster_resource.chef_server_key
      ) do
        require 'chef/knife/vault_refresh'

        Chef::Knife::VaultRefresh.load_deps
        knife = Chef::Knife::VaultRefresh.new
        knife.config[:vault_mode] = 'client'

        vaults = [node['clc_library']['admin_password_vault']]
        unless cluster_resource.cluster_vaults.nil?
          vaults.concat(cluster_resource.cluster_vaults)
        end

        vaults.each do |v|
          Chef::Log.info "Refreshing vault #{node["provisioner"]["vault_bag"]}/#{v}"
          knife.name_args = [node["provisioner"]["vault_bag"], v]
          knife.run
        end
      end
    end
    action :run
  end

  if cluster_resource.converge
    converge = machine_batch do
      machine_options.keys.each do |machine_name|
        machine machine_name do
          machine_options machine_options[machine_name]
          action :converge_only
        end
      end
    end
    if !converge.updated_by_last_action?
      updated = false
    end
  end

  cluster_resource.updated_by_last_action(updated)
end