module Wombat::Common

Public Instance Methods

audio?() click to toggle source
# File lib/wombat/common.rb, line 138
def audio?
  is_mac? && conf['audio']
end
azure_provider_tag() click to toggle source

Return the Azure Provider tag that should be applied to resource

# File lib/wombat/common.rb, line 298
def azure_provider_tag
  "33194f91-eb5f-4110-827a-e95f640a9e46".upcase
end
banner(msg) click to toggle source
bootstrap_aws() click to toggle source
# File lib/wombat/common.rb, line 50
def bootstrap_aws
  @workstation_passwd = wombat['workstations']['password']
  rendered = ERB.new(File.read("#{conf['template_dir']}/bootstrap-aws.erb"), nil, '-').result(binding)
  Dir.mkdir("#{conf['packer_dir']}/scripts", 0755) unless File.exist?("#{conf['packer_dir']}/scripts")
  File.open("#{conf['packer_dir']}/scripts/bootstrap-aws.txt", 'w') { |file| file.puts rendered }
  banner("Generated: #{conf['packer_dir']}/scripts/bootstrap-aws.txt")
end
build_nodes() click to toggle source
# File lib/wombat/common.rb, line 86
def build_nodes
  build_nodes = {}
  1.upto(wombat['build-nodes']['count'].to_i) do |i|
    build_nodes["build-node-#{i}"] = i
  end
  build_nodes
end
calculate_templates() click to toggle source
# File lib/wombat/common.rb, line 147
def calculate_templates
globs = "*.json"
  Dir.chdir(conf['packer_dir']) do
    Array(globs).
      map { |glob| result = Dir.glob("#{glob}"); result.empty? ? glob : result }.
      flatten.
      sort.
      delete_if { |file| file =~ /\.variables\./ }.
      map { |template| template.sub(/\.json$/, '') }
  end
end
conf() click to toggle source
# File lib/wombat/common.rb, line 119
def conf
  conf = wombat['conf']
  conf ||= {}
  conf['files_dir'] ||= 'files'
  conf['key_dir'] ||= 'keys'
  conf['cookbook_dir'] ||= 'cookbooks'
  conf['packer_dir'] ||= 'packer'
  conf['log_dir'] ||= 'logs'
  conf['stack_dir'] ||= 'stacks'
  conf['template_dir'] ||= 'templates'
  conf['timeout'] ||= 7200
  conf['audio'] ||= false
  conf
end
connect_azure() click to toggle source

Connect to Azure using environment variables

# File lib/wombat/common.rb, line 305
def connect_azure

    # Create the connection to Azure using the information in the environment variables
    tenant_id = ENV['AZURE_TENANT_ID']
    client_id = ENV['AZURE_CLIENT_ID']
    client_secret = ENV['AZURE_CLIENT_SECRET']

    token_provider = MsRestAzure::ApplicationTokenProvider.new(tenant_id, client_id, client_secret)
    MsRest::TokenCredentials.new(token_provider)
end
create_infranodes_json() click to toggle source
# File lib/wombat/common.rb, line 102
def create_infranodes_json
  infranodes_file_path = File.join(conf['files_dir'], 'infranodes-info.json')
  if File.exists?(infranodes_file_path) && is_valid_json?(infranodes_file_path)
    current_state = JSON(File.read(infranodes_file_path))
  else
    current_state = nil
  end
  return if current_state == infranodes # yay idempotence
  File.open(infranodes_file_path, 'w') do |f|
    f.puts JSON.pretty_generate(infranodes)
  end
end
create_resource_group(resource_management_client, name, location, owner = nil, rgtags = {}) click to toggle source
# File lib/wombat/common.rb, line 369
def create_resource_group(resource_management_client, name, location, owner = nil, rgtags = {})

  # Check that the resource group exists
  banner(format("Checking for resource group: %s", name))
  status = resource_management_client.resource_groups.check_existence(name)
  if status
    puts "resource group already exists"
  else
    puts format("creating new resource group in '%s'", location)

    # Set the parameters for the resource group
    resource_group = Azure::ARM::Resources::Models::ResourceGroup.new
    resource_group.location = location

    # Create hash to be used as tags on the resource group
    tags = {
      owner: ENV['USER'],
      provider: azure_provider_tag
    }

    # If an owner has been specified in the wombat file override the owner value
    if !owner.nil?
      tags[:owner] = owner
    end

    # Determine if there are any tags specified in the azure wmbat section that need to be added
    if !rgtags.nil? && rgtags.length > 0

      # Check to see if there are more than 15 tags in which case output a warning
      if rgtags.length > 14
        warn ('More than 15 tags have been specified, only the first 15 will be added.  This is a restriction in Azure.')
      end

      # Iterate around the tags and add each one to the tags array, up to 15
      rgtags.each_with_index do |(key, value), index|
        tags[key] = value

        if index == 12
          break
        end
      end

    end

    # add the tags hash to the parameters
    resource_group.tags = rgtags

    # Create the resource group
    resource_management_client.resource_groups.create_or_update(name, resource_group)
  end    
end
deployment_state(rg_name, deployment_name) click to toggle source

Get the state of the specified deployment

Attributes
  • rg_name - Name of the resource group being deployed to

  • deployment_name - Name of the deployment that is currently being processed

# File lib/wombat/common.rb, line 364
def deployment_state(rg_name, deployment_name)
  deployments = resource_management_client.deployments.get(rg_name, deployment_name)
  deployments.properties.provisioning_state
end
duration(total) click to toggle source
# File lib/wombat/common.rb, line 23
def duration(total)
  total = 0 if total.nil?
  minutes = (total / 60).to_i
  seconds = (total - (minutes * 60))
  format("%dm%.2fs", minutes, seconds)
end
follow_azure_deployment(rg_name, deployment_name) click to toggle source

Track the progress of the deployment in Azure

Attributes
  • rg_name - Name of the resource group being deployed to

  • deployment_name - Name of the deployment that is currently being processed

# File lib/wombat/common.rb, line 322
def follow_azure_deployment(rg_name, deployment_name)

  end_provisioning_states = 'Canceled,Failed,Deleted,Succeeded'
  end_provisioning_state_reached = false

  until end_provisioning_state_reached
    list_outstanding_deployment_operations(rg_name, deployment_name)
    sleep 10
    deployment_provisioning_state = deployment_state(rg_name, deployment_name)
    end_provisioning_state_reached = end_provisioning_states.split(',').include?(deployment_provisioning_state)
  end
  info format("Resource Template deployment reached end state of %s", deployment_provisioning_state)
end
info(msg) click to toggle source
# File lib/wombat/common.rb, line 15
def info(msg)
  puts "    #{msg}"
end
infranodes() click to toggle source
# File lib/wombat/common.rb, line 77
def infranodes
  unless wombat['infranodes'].nil?
    wombat['infranodes'].sort
  else
    puts 'No infranodes listed in wombat.yml'
    {}
  end
end
is_mac?() click to toggle source
# File lib/wombat/common.rb, line 134
def is_mac?
  (/darwin/ =~ RUBY_PLATFORM) != nil
end
is_valid_json?(file) click to toggle source
# File lib/wombat/common.rb, line 288
def is_valid_json?(file)
  begin
    JSON.parse(file)
    true
  rescue JSON::ParserError => e
    false
  end
end
linux() click to toggle source
# File lib/wombat/common.rb, line 115
def linux
  wombat['linux'].nil? ? 'ubuntu' : wombat['linux']
end
list_outstanding_deployment_operations(rg_name, deployment_name) click to toggle source

Get a list of the outstanding deployment operations

Attributes
  • rg_name - Name of the resource group being deployed to

  • deployment_name - Name of the deployment that is currently being processed

# File lib/wombat/common.rb, line 342
def list_outstanding_deployment_operations(rg_name, deployment_name)
  end_operation_states = 'Failed,Succeeded'
  deployment_operations = resource_management_client.deployment_operations.list(rg_name, deployment_name)
  deployment_operations.each do |val|
    resource_provisioning_state = val.properties.provisioning_state
    unless val.properties.target_resource.nil?
      resource_name = val.properties.target_resource.resource_name
      resource_type = val.properties.target_resource.resource_type
    end
    end_operation_state_reached = end_operation_states.split(',').include?(resource_provisioning_state)
    unless end_operation_state_reached
      info format("resource %s '%s' provisioning status is %s", resource_type, resource_name, resource_provisioning_state)
    end
  end
end
lock() click to toggle source
# File lib/wombat/common.rb, line 41
def lock
  if !File.exist?('wombat.lock')
    warn('No wombat.lock found')
    return 1
  else
    JSON.parse(File.read('wombat.lock'))
  end
end
logs() click to toggle source
# File lib/wombat/common.rb, line 142
def logs
  path = "#{conf['log_dir']}/#{cloud}*.log"
  Dir.glob(path).reject { |l| !l.match(wombat['linux']) }
end
parse_log(log, cloud) click to toggle source
# File lib/wombat/common.rb, line 58
def parse_log(log, cloud)
  regex = case cloud
          when 'gcp'
            'A disk image was created:'
          when 'azure'

            if !wombat['azure'].key?('use_managed_disks') || !wombat['azure']['use_managed_disks']
              '^OSDiskUri:'
            else
              '^ManagedDiskOSDiskUri:'
            end

          else
            "#{wombat['aws']['region']}:"
          end

  File.read(log).split("\n").grep(/#{regex}/) {|x| x.split[1]}.last
end
update_lock(cloud) click to toggle source
# File lib/wombat/common.rb, line 159
def update_lock(cloud)
  copy = {}
  copy = wombat

  # Check that the copy contains a key for the named cloud
  unless copy.key?(cloud)
    throw "The Cloud '#{cloud}' is not specified in Wombat"
  end

  # Determine the region/location/zone for the specific cloud
  case cloud
  when 'aws'
    region = copy['aws']['region']
  when 'azure'
    region = copy['azure']['location']
  when 'gce'
    region = copy['gce']['zone']
  end

  linux = copy['linux']
  copy['amis'] = { region => {} }

  if logs.length == 0
    warn('No logs found - skipping lock update')
  else
    logs.each do |log|
      case log
      when /build-node/
        copy['amis'][region]['build-node'] ||= {}
        num = log.split('-')[3]
        copy['amis'][region]['build-node'].store(num, parse_log(log, cloud))
      when /workstation/
        copy['amis'][region]['workstation'] ||= {}
        num = log.split('-')[2]
        copy['amis'][region]['workstation'].store(num, parse_log(log, cloud))
      when /infranodes/
        copy['amis'][region]['infranodes'] ||= {}
        name = log.split('-')[2]
        copy['amis'][region]['infranodes'].store(name, parse_log(log, cloud))
      else
        instance = log.match("#{cloud}-(.*)-#{linux}\.log")[1]
        copy['amis'][region].store(instance, parse_log(log, cloud))
      end
    end
    copy['last_updated'] = Time.now.gmtime.strftime('%Y%m%d%H%M%S')
    banner('Updating wombat.lock')
    File.open('wombat.lock', 'w') do |f|
      f.write(JSON.pretty_generate(copy))
    end
  end
end
update_template(cloud) click to toggle source
# File lib/wombat/common.rb, line 211
def update_template(cloud)
  if lock == 1
    warn('No lock - skipping template creation')
  else

    @demo = lock['name']
    @version = lock['version']
    @ttl = lock['ttl']

    # Determine the region/location/zone for the specific cloud
    case cloud
    when 'aws'
      region = lock['aws']['region']
      template_files = {
        "cfn.json.erb": "#{conf['stack_dir']}/#{@demo}.json"
      }
      @chef_server_ami = lock['amis'][region]['chef-server']
      @automate_ami = lock['amis'][region]['automate']
      @compliance_ami = lock['amis'][region]['compliance']
      @availability_zone = lock['aws']['az']
      @iam_roles = lock['aws']['iam_roles']
    when 'azure'
      region = lock['azure']['location']
      @storage_account = lock['azure']['storage_account']

      template_files = {}

      # determine whether to use VHD or Managed Disks
      if !lock['azure'].key?('use_managed_disks') || !lock['azure']['use_managed_disks']
        template_files['arm.vhd.json.erb'] = format("%s/%s.json", conf['stack_dir'], @demo)
      else
        template_files['arm.md.json.erb'] = format("%s/%s.json", conf['stack_dir'], @demo)
      end

      @chef_server_uri = lock['amis'][region]['chef-server']
      @automate_uri = lock['amis'][region]['automate']
      @compliance_uri = lock['amis'][region]['compliance']
      @password = lock['workstations']['password']
      @public_key = File.read("#{conf['key_dir']}/public.pub").chomp

      # Set the Azure Tag used to identify Chef products in Azure
      @chef_tag = azure_provider_tag
    when 'gce'
      region = lock['gce']['zone']
    end

    if lock['amis'][region].key?('build-node')
      @build_nodes = lock['build-nodes']['count'].to_i
      @build_node_ami = {}
      1.upto(@build_nodes) do |i|
        @build_node_ami[i] = lock['amis'][region]['build-node'][i.to_s]
      end
    end

    @infra = {}
    infranodes.each do |name, _rl|
      @infra[name] = lock['amis'][region]['infranodes'][name]
    end

    if lock['amis'][region].key?('workstation')
      @workstations = lock['workstations']['count'].to_i
      @workstation_ami = {}
      1.upto(@workstations) do |i|
        @workstation_ami[i] = lock['amis'][region]['workstation'][i.to_s]
      end
    end

    # Iterate around each of the template files that have been defined and render it
    template_files.each do |template_file, destination|
      rendered_cfn = ERB.new(File.read("#{conf['template_dir']}/#{template_file}"), nil, '-').result(binding)
      Dir.mkdir(conf['stack_dir'], 0755) unless File.exist?(conf['stack_dir'])
      File.open("#{destination}", 'w') { |file| file.puts rendered_cfn }
      banner("Generated: #{destination}")
    end
  end
end
warn(msg) click to toggle source
# File lib/wombat/common.rb, line 19
def warn(msg)
  puts ">>> #{msg}"
end
wombat() click to toggle source
# File lib/wombat/common.rb, line 30
def wombat
  @wombat_yml ||= ENV['WOMBAT_YML'] unless ENV['WOMBAT_YML'].nil?
  @wombat_yml ||= 'wombat.yml'
  if !File.exist?(@wombat_yml)
    warn('No wombat.yml found, copying example')
    gen_dir = "#{File.expand_path("../..", File.dirname(__FILE__))}/generator_files"
    FileUtils.cp_r "#{gen_dir}/wombat.yml", Dir.pwd
  end
  YAML.load(File.read(@wombat_yml))
end
workstations() click to toggle source
# File lib/wombat/common.rb, line 94
def workstations
  workstations = {}
  1.upto(wombat['workstations']['count'].to_i) do |i|
    workstations["workstation-#{i}"] = i
  end
  workstations
end