require 'active_support' require 'active_support/time'
require 'aws-sdk-ec2' require 'aws-sdk-autoscaling'
namespace :load do
task :defaults do set :aws_autoscaling, true set :aws_region, 'ap-northeast-1' set :aws_deploy_roles, [:app, :web, :db] set :aws_autoscale_ami_prefix, '' end
end
namespace :deploy do
before :starting, :check_autoscaling_hooks do invoke 'autoscaling_deploy:setup_instances' if fetch(:aws_autoscaling) end
end
namespace :autoscaling_deploy do
desc 'Add server from Auto Scaling Group.' task :setup_instances do ec2_instances = fetch_ec2_instances aws_deploy_roles = fetch(:aws_deploy_roles) aws_deploy_user = fetch(:aws_deploy_user) ec2_instances.each { |instance| if ec2_instances.first == instance server instance, user: aws_deploy_user, roles: aws_deploy_roles, primary: true puts("First Server: #{instance} - #{aws_deploy_roles}") else server instance, user: aws_deploy_user, roles: sanitize_roles(aws_deploy_roles) puts("Server: #{instance} - #{sanitize_roles(aws_deploy_roles)}") end } end def fetch_ec2_instances region = fetch(:aws_region) key = fetch(:aws_access_key_id) secret = fetch(:aws_secret_access_key) group_name = fetch(:aws_autoscaling_group_name) puts("Fetching servers for Auto Scaling Group: #{group_name}") instances = get_instances_ip(region, key, secret, group_name) puts("Found #{instances.count} servers (#{instances.join(' , ')}) for Auto Scaling Group: #{group_name} ") instances end # Get Autoscale Group Healthy Instance Public IP's def get_instances_ip(region, key, secret, group_name) credentials = { region: region, credentials: Aws::Credentials.new(key, secret) } instances_of_as = get_instances(credentials, group_name) autoscaling_dns = [] ec2 = Aws::EC2::Resource.new(credentials) instances_of_as.each do |instance| if instance.health_status != 'Healthy' puts "Autoscaling: Skipping unhealthy instance #{instance.instance_id}" else autoscaling_dns << ec2.instance(instance.instance_id).public_ip_address end end autoscaling_dns end # Get Autoscale Group Instance Info def get_instances(credentials, group_name) as = Aws::AutoScaling::Client.new(credentials) instances_of_as = as.describe_auto_scaling_groups( auto_scaling_group_names: [group_name], max_records: 1, ).auto_scaling_groups[0].instances instances_of_as end # remove :db (for migrations), remove :primary => :true (for assets precompile) for primary server def sanitize_roles(roles) roles.inject([]) { |acc, role| if !role.is_a?(Hash) acc << role if role != :db else acc << role.reject { |k, v| k == :primary } end acc } end
end