summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--[-rwxr-xr-x]lib/ansible_helper.rb10
-rw-r--r--lib/aws_command.rb144
-rw-r--r--lib/aws_helper.rb82
-rw-r--r--[-rwxr-xr-x]lib/gce_command.rb12
-rw-r--r--[-rwxr-xr-x]lib/gce_helper.rb16
-rw-r--r--[-rwxr-xr-x]lib/launch_helper.rb4
6 files changed, 255 insertions, 13 deletions
diff --git a/lib/ansible_helper.rb b/lib/ansible_helper.rb
index 876c16a44..76af73b0d 100755..100644
--- a/lib/ansible_helper.rb
+++ b/lib/ansible_helper.rb
@@ -60,7 +60,7 @@ extra_vars: #{@extra_vars.to_json}
end
def self.for_gce
- ah = AnsibleHelper.new
+ ah = AnsibleHelper.new
# GCE specific configs
gce_ini = "#{MYDIR}/../inventory/gce/gce.ini"
@@ -85,6 +85,14 @@ extra_vars: #{@extra_vars.to_json}
return ah
end
+ def self.for_aws
+ ah = AnsibleHelper.new
+
+ ah.inventory = 'inventory/aws/ec2.py'
+ return ah
+ end
+
+
def ignore_bug_6407
puts
puts %q[ .---- Spurious warning "It is unnecessary to use '{{' in loops" (ansible bug 6407) ----.]
diff --git a/lib/aws_command.rb b/lib/aws_command.rb
new file mode 100644
index 000000000..d471557b8
--- /dev/null
+++ b/lib/aws_command.rb
@@ -0,0 +1,144 @@
+require 'thor'
+
+require_relative 'aws_helper'
+require_relative 'launch_helper'
+
+module OpenShift
+ module Ops
+ class AwsCommand < Thor
+ # WARNING: we do not currently support environments with hyphens in the name
+ SUPPORTED_ENVS = %w(prod stg int tint kint test jint)
+
+ option :type, :required => true, :enum => LaunchHelper.get_aws_host_types,
+ :desc => 'The host type of the new instances.'
+ option :env, :required => true, :aliases => '-e', :enum => SUPPORTED_ENVS,
+ :desc => 'The environment of the new instances.'
+ option :count, :default => 1, :aliases => '-c', :type => :numeric,
+ :desc => 'The number of instances to create'
+ option :tag, :type => :array,
+ :desc => 'The tag(s) to add to the new instances. Allowed characters are letters, numbers, and hyphens.'
+ desc "launch", "Launches instances."
+ def launch()
+ AwsHelper.check_creds()
+
+ # Expand all of the instance names so that we have a complete array
+ names = []
+ options[:count].times { names << "#{options[:env]}-#{options[:type]}-#{SecureRandom.hex(5)}" }
+
+ ah = AnsibleHelper.for_aws()
+
+ # AWS specific configs
+ ah.extra_vars['oo_new_inst_names'] = names
+ ah.extra_vars['oo_new_inst_tags'] = options[:tag]
+ ah.extra_vars['oo_env'] = options[:env]
+
+ # Add a created by tag
+ ah.extra_vars['oo_new_inst_tags'] = {} if ah.extra_vars['oo_new_inst_tags'].nil?
+
+ ah.extra_vars['oo_new_inst_tags']["created-by"] = ENV['USER']
+ ah.extra_vars['oo_new_inst_tags'].merge!(AwsHelper.generate_env_tag(options[:env]))
+ ah.extra_vars['oo_new_inst_tags'].merge!(AwsHelper.generate_host_type_tag(options[:type]))
+ ah.extra_vars['oo_new_inst_tags'].merge!(AwsHelper.generate_env_host_type_tag(options[:env], options[:type]))
+
+ puts
+ puts 'Creating instance(s) in AWS...'
+ ah.ignore_bug_6407
+
+ # Make sure we're completely up to date before launching
+ clear_cache()
+ ah.run_playbook("playbooks/aws/#{options[:type]}/launch.yml")
+ ensure
+ # This is so that if we a config right after a launch, the newly launched instances will be
+ # in the list.
+ clear_cache()
+ end
+
+ desc "clear-cache", 'Clear the inventory cache'
+ def clear_cache()
+ print "Clearing inventory cache... "
+ AwsHelper.clear_inventory_cache()
+ puts "Done."
+ end
+
+ option :name, :required => false, :type => :string,
+ :desc => 'The name of the instance to configure.'
+ option :env, :required => false, :aliases => '-e', :enum => SUPPORTED_ENVS,
+ :desc => 'The environment of the new instances.'
+ option :type, :required => false, :enum => LaunchHelper.get_aws_host_types,
+ :desc => 'The type of the instances to configure.'
+ desc "config", 'Configures instances.'
+ def config()
+ ah = AnsibleHelper.for_aws()
+
+ abort 'Error: you can\'t specify both --name and --type' unless options[:type].nil? || options[:name].nil?
+
+ abort 'Error: you can\'t specify both --name and --env' unless options[:env].nil? || options[:name].nil?
+
+ host_type = nil
+ if options[:name]
+ details = AwsHelper.get_host_details(options[:name])
+ ah.extra_vars['oo_host_group_exp'] = options[:name]
+ ah.extra_vars['oo_env'] = details['env']
+ host_type = details['host-type']
+ elsif options[:type] && options[:env]
+ oo_env_host_type_tag = AwsHelper.generate_env_host_type_tag_name(options[:env], options[:type])
+ ah.extra_vars['oo_host_group_exp'] = "groups['#{oo_env_host_type_tag}']"
+ ah.extra_vars['oo_env'] = options[:env]
+ host_type = options[:type]
+ else
+ abort 'Error: you need to specify either --name or (--type and --env)'
+ end
+
+ puts
+ puts "Configuring #{options[:type]} instance(s) in AWS..."
+ ah.ignore_bug_6407
+
+ ah.run_playbook("playbooks/aws/#{host_type}/config.yml")
+ end
+
+ desc "list", "Lists instances."
+ def list()
+ AwsHelper.check_creds()
+ hosts = AwsHelper.get_hosts()
+
+ puts
+ puts "Instances"
+ puts "---------"
+ hosts.each { |h| puts " #{h.name}.#{h.env}" }
+ puts
+ end
+
+ desc "ssh", "Ssh to an instance"
+ def ssh(*ssh_ops, host)
+ if host =~ /^([\w\d_.-]+)@([\w\d-_.]+)/
+ user = $1
+ host = $2
+ end
+
+ details = AwsHelper.get_host_details(host)
+ abort "\nError: Instance [#{host}] is not RUNNING\n\n" unless details['ec2_state'] == 'running'
+
+ cmd = "ssh #{ssh_ops.join(' ')}"
+
+ if user.nil?
+ cmd += " "
+ else
+ cmd += " #{user}@"
+ end
+
+ cmd += "#{details['ec2_ip_address']}"
+
+ exec(cmd)
+ end
+
+ desc 'types', 'Displays instance types'
+ def types()
+ puts
+ puts "Available Host Types"
+ puts "--------------------"
+ LaunchHelper.get_aws_host_types.each { |t| puts " #{t}" }
+ puts
+ end
+ end
+ end
+end
diff --git a/lib/aws_helper.rb b/lib/aws_helper.rb
new file mode 100644
index 000000000..6d213107b
--- /dev/null
+++ b/lib/aws_helper.rb
@@ -0,0 +1,82 @@
+require 'fileutils'
+
+module OpenShift
+ module Ops
+ class AwsHelper
+ MYDIR = File.expand_path(File.dirname(__FILE__))
+
+ def self.get_list()
+ cmd = "#{MYDIR}/../inventory/aws/ec2.py --list"
+ hosts = %x[#{cmd} 2>&1]
+
+ raise "Error: failed to list hosts\n#{hosts}" unless $?.exitstatus == 0
+ return JSON.parse(hosts)
+ end
+
+ def self.get_hosts()
+ hosts = get_list()
+
+ retval = []
+ hosts['_meta']['hostvars'].each do |host, info|
+ retval << OpenStruct.new({
+ :name => info['ec2_tag_Name'],
+ :env => info['ec2_tag_environment'] || 'UNSET',
+ :external_ip => info['ec2_ip_address'],
+ :public_dns => info['ec2_public_dns_name']
+ })
+ end
+
+ retval.sort_by! { |h| [h.env, h.name] }
+
+ return retval
+ end
+
+ def self.get_host_details(host)
+ hosts = get_list()
+ dns_names = hosts["tag_Name_#{host}"]
+
+ raise "Error: host not found [#{host}]" if dns_names.nil?
+
+ return hosts['_meta']['hostvars'][dns_names.first]
+ end
+
+ def self.check_creds()
+ raise "AWS_ACCESS_KEY_ID environment variable must be set" if ENV['AWS_ACCESS_KEY_ID'].nil?
+ raise "AWS_SECRET_ACCESS_KEY environment variable must be set" if ENV['AWS_SECRET_ACCESS_KEY'].nil?
+ end
+
+ def self.clear_inventory_cache()
+ path = "#{ENV['HOME']}/.ansible/tmp"
+ cache_files = ["#{path}/ansible-ec2.cache", "#{path}/ansible-ec2.index"]
+ FileUtils.rm(cache_files)
+ end
+
+ def self.generate_env_tag(env)
+ return { "environment" => env }
+ end
+
+ def self.generate_env_tag_name(env)
+ h = generate_env_tag(env)
+ return "tag_#{h.keys.first}_#{h.values.first}"
+ end
+
+ def self.generate_host_type_tag(host_type)
+ return { "host-type" => host_type }
+ end
+
+ def self.generate_host_type_tag_name(host_type)
+ h = generate_host_type_tag(host_type)
+ return "tag_#{h.keys.first}_#{h.values.first}"
+ end
+
+ def self.generate_env_host_type_tag(env, host_type)
+ return { "env-host-type" => "#{env}-#{host_type}" }
+ end
+
+ def self.generate_env_host_type_tag_name(env, host_type)
+ h = generate_env_host_type_tag(env, host_type)
+ return "tag_#{h.keys.first}_#{h.values.first}"
+ end
+ end
+ end
+end
diff --git a/lib/gce_command.rb b/lib/gce_command.rb
index 6a6b46228..ce3737a19 100755..100644
--- a/lib/gce_command.rb
+++ b/lib/gce_command.rb
@@ -125,17 +125,12 @@ module OpenShift
desc "list", "Lists instances."
def list()
- hosts = GceHelper.list_hosts()
-
- data = {}
- hosts.each do |key,value|
- value.each { |h| (data[h] ||= []) << key }
- end
+ hosts = GceHelper.get_hosts()
puts
puts "Instances"
puts "---------"
- data.keys.sort.each { |k| puts " #{k}" }
+ hosts.each { |k| puts " #{k.name}" }
puts
end
@@ -177,13 +172,10 @@ module OpenShift
desc "ssh", "Ssh to an instance"
def ssh(*ssh_ops, host)
- puts host
if host =~ /^([\w\d_.-]+)@([\w\d-_.]+)/
user = $1
host = $2
end
- puts "user=#{user}"
- puts "host=#{host}"
details = GceHelper.get_host_details(host)
abort "\nError: Instance [#{host}] is not RUNNING\n\n" unless details['gce_status'] == 'RUNNING'
diff --git a/lib/gce_helper.rb b/lib/gce_helper.rb
index 6c0f57cf3..2ff716ce1 100755..100644
--- a/lib/gce_helper.rb
+++ b/lib/gce_helper.rb
@@ -1,15 +1,27 @@
+require 'ostruct'
+
module OpenShift
module Ops
class GceHelper
MYDIR = File.expand_path(File.dirname(__FILE__))
- def self.list_hosts()
+ def self.get_hosts()
cmd = "#{MYDIR}/../inventory/gce/gce.py --list"
hosts = %x[#{cmd} 2>&1]
raise "Error: failed to list hosts\n#{hosts}" unless $?.exitstatus == 0
- return JSON.parse(hosts)
+ # invert the hash so that it's key is the host, and values is an array of metadata
+ data = {}
+ JSON.parse(hosts).each do |key,value|
+ value.each { |h| (data[h] ||= []) << key }
+ end
+
+ # For now, we only care about the name. In the future, we may want the other metadata included.
+ retval = []
+ data.keys.sort.each { |k| retval << OpenStruct.new({ :name => k }) }
+
+ return retval
end
def self.get_host_details(host)
diff --git a/lib/launch_helper.rb b/lib/launch_helper.rb
index 2033f3ddb..0fe5ea6dc 100755..100644
--- a/lib/launch_helper.rb
+++ b/lib/launch_helper.rb
@@ -21,6 +21,10 @@ module OpenShift
def self.get_gce_host_types()
return Dir.glob("#{MYDIR}/../playbooks/gce/*").map { |d| File.basename(d) }
end
+
+ def self.get_aws_host_types()
+ return Dir.glob("#{MYDIR}/../playbooks/aws/*").map { |d| File.basename(d) }
+ end
end
end
end