From a587014e0cf145c0766e0c11d4b29376b3bb8545 Mon Sep 17 00:00:00 2001 From: Chris Heald Date: Tue, 15 Mar 2016 11:30:26 -0700 Subject: [PATCH 1/5] Add support for ec2_filters, which overrides the standard filtering --- lib/cap-ec2/ec2-handler.rb | 42 ++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/lib/cap-ec2/ec2-handler.rb b/lib/cap-ec2/ec2-handler.rb index 2d54887..e6648c1 100644 --- a/lib/cap-ec2/ec2-handler.rb +++ b/lib/cap-ec2/ec2-handler.rb @@ -54,24 +54,44 @@ def application Capistrano::Configuration.env.fetch(:application).to_s end + def filter + f = Capistrano::Configuration.env.fetch(:ec2_filter) + f.respond_to?(:call) ? f.call : f + end + + def default_filter + { + tag(project_tag) => "*#{application}*", + 'instance-state-name' => "running" + } + end + def tag(tag_name) "tag:#{tag_name}" end + def get_servers_for_filter(filter) + @ec2.flat_map do |_, ec2| + instances = ec2.instances.filter('instance-state-name', 'running') + filter.each {|key, val| instances = instances.filter(key.to_s, *Array(val).map(&:to_s)) } + instances.to_a + end + end + def get_servers_for_role(role) - servers = [] - @ec2.each do |_, ec2| - instances = ec2.instances - .filter(tag(project_tag), "*#{application}*") - .filter('instance-state-name', 'running') - servers << instances.select do |i| - instance_has_tag?(i, roles_tag, role) && + servers = get_servers_for_filter(filter || default_filter) + servers.sort_by {|s| s.tags["Name"] || ''}.select do |i| + instance_has_tag?(i, roles_tag, role) && + (filter || instance_has_tag?(i, stages_tag, stage) && - instance_has_tag?(i, project_tag, application) && - (fetch(:ec2_filter_by_status_ok?) ? instance_status_ok?(i) : true) - end + instance_has_tag?(i, project_tag, application) + ) + end + if fetch(:ec2_filter_by_status_ok?) + servers.select {|server| instance_status_ok? server } + else + servers end - servers.flatten.sort_by {|s| s.tags["Name"] || ''} end def get_server(instance_id) From 559c0eeeeb26fc83e12575a3b64d2a7d7f1b0bf1 Mon Sep 17 00:00:00 2001 From: Chris Heald Date: Tue, 15 Mar 2016 12:50:56 -0700 Subject: [PATCH 2/5] Don't need instance-state-name in the default filter, it gets added during filtering --- lib/cap-ec2/ec2-handler.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/cap-ec2/ec2-handler.rb b/lib/cap-ec2/ec2-handler.rb index e6648c1..e57138f 100644 --- a/lib/cap-ec2/ec2-handler.rb +++ b/lib/cap-ec2/ec2-handler.rb @@ -60,10 +60,7 @@ def filter end def default_filter - { - tag(project_tag) => "*#{application}*", - 'instance-state-name' => "running" - } + { tag(project_tag) => "*#{application}*" } end def tag(tag_name) From 9bd1659136a83c8a6a54730275323a02ce1927db Mon Sep 17 00:00:00 2001 From: Chris Heald Date: Thu, 21 Apr 2016 14:51:39 -0700 Subject: [PATCH 3/5] Actually filter results. Whoops. --- lib/cap-ec2/ec2-handler.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/cap-ec2/ec2-handler.rb b/lib/cap-ec2/ec2-handler.rb index e57138f..d3ffda6 100644 --- a/lib/cap-ec2/ec2-handler.rb +++ b/lib/cap-ec2/ec2-handler.rb @@ -76,14 +76,14 @@ def get_servers_for_filter(filter) end def get_servers_for_role(role) - servers = get_servers_for_filter(filter || default_filter) - servers.sort_by {|s| s.tags["Name"] || ''}.select do |i| - instance_has_tag?(i, roles_tag, role) && - (filter || - instance_has_tag?(i, stages_tag, stage) && - instance_has_tag?(i, project_tag, application) - ) - end + servers = get_servers_for_filter(filter || default_filter). + sort_by {|s| s.tags["Name"] || ''}.select do |i| + instance_has_tag?(i, roles_tag, role) && + (filter || + instance_has_tag?(i, stages_tag, stage) && + instance_has_tag?(i, project_tag, application) + ) + end if fetch(:ec2_filter_by_status_ok?) servers.select {|server| instance_status_ok? server } else From 9dbdd105afac66ef0d980842b4440b488426461f Mon Sep 17 00:00:00 2001 From: Chris Heald Date: Thu, 21 Apr 2016 15:36:17 -0700 Subject: [PATCH 4/5] Re-add support for multiple roles as an option in ec2_role --- lib/cap-ec2/capistrano.rb | 7 +++--- lib/cap-ec2/ec2-handler.rb | 46 ++++++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/lib/cap-ec2/capistrano.rb b/lib/cap-ec2/capistrano.rb index 9df98ce..09b22f1 100644 --- a/lib/cap-ec2/capistrano.rb +++ b/lib/cap-ec2/capistrano.rb @@ -19,9 +19,10 @@ def ec2_handler end def ec2_role(name, options={}) - ec2_handler.get_servers_for_role(name).each do |server| - env.role(name, CapEC2::Utils.contact_point(server), - options_with_instance_id(options, server)) + ec2_handler.get_servers_for_role(options.fetch(:roles, name)).each do |roles, servers| + servers.each do |server| + env.role(name, CapEC2::Utils.contact_point(server), options_with_instance_id(options, server)) + end end end diff --git a/lib/cap-ec2/ec2-handler.rb b/lib/cap-ec2/ec2-handler.rb index d3ffda6..2b8c303 100644 --- a/lib/cap-ec2/ec2-handler.rb +++ b/lib/cap-ec2/ec2-handler.rb @@ -22,24 +22,24 @@ def ec2_connect(region=nil) def status_table CapEC2::StatusTable.new( - defined_roles.map {|r| get_servers_for_role(r)}.flatten.uniq {|i| i.instance_id} + defined_roles.map {|r| get_servers_for_role(r).values }.flatten.uniq {|i| i.instance_id} ) end def server_names - puts defined_roles.map {|r| get_servers_for_role(r)} - .flatten - .uniq {|i| i.instance_id} - .map {|i| i.tags["Name"]} - .join("\n") + puts defined_roles.map {|r| get_servers_for_role(r).values } + .flatten + .uniq {|i| i.instance_id} + .map {|i| i.tags["Name"]} + .join("\n") end def instance_ids - puts defined_roles.map {|r| get_servers_for_role(r)} - .flatten - .uniq {|i| i.instance_id} - .map {|i| i.instance_id} - .join("\n") + puts defined_roles.map {|r| get_servers_for_role(r).values } + .flatten + .uniq {|i| i.instance_id} + .map {|i| i.instance_id} + .join("\n") end def defined_roles @@ -75,19 +75,22 @@ def get_servers_for_filter(filter) end end - def get_servers_for_role(role) + def get_servers_for_role(roles) servers = get_servers_for_filter(filter || default_filter). sort_by {|s| s.tags["Name"] || ''}.select do |i| - instance_has_tag?(i, roles_tag, role) && + instance_has_tag?(i, roles_tag, roles) && (filter || instance_has_tag?(i, stages_tag, stage) && instance_has_tag?(i, project_tag, application) ) end - if fetch(:ec2_filter_by_status_ok?) - servers.select {|server| instance_status_ok? server } - else - servers + servers.each_with_object({}) do |server, role_map| + matching_roles = instance_tags_matching(server, roles_tag, roles) + if matching_roles.any? + if !fetch(:ec2_filter_by_status_ok?) || instance_status_ok?(server) + (role_map[matching_roles] ||= []) << server + end + end end end @@ -99,8 +102,13 @@ def get_server(instance_id) private - def instance_has_tag?(instance, key, value) - (instance.tags[key] || '').split(',').map(&:strip).include?(value.to_s) + def instance_has_tag?(instance, key, values) + instance_tags_matching(instance, key, values).any? + end + + def instance_tags_matching(instance, key, values) + tags_array = (instance.tags[key] || "").split(',').map(&:strip) + tags_array & (Array(values).map(&:to_s)) end def instance_status_ok?(instance) From 69cd5cdb39ab08d51bf52777c566417257843241 Mon Sep 17 00:00:00 2001 From: Chris Heald Date: Thu, 21 Apr 2016 16:05:36 -0700 Subject: [PATCH 5/5] Add filtering by given and aliased role names. Add internal DNS to table display. --- lib/cap-ec2/capistrano.rb | 6 +++--- lib/cap-ec2/ec2-handler.rb | 2 +- lib/cap-ec2/status-table.rb | 8 +++++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/cap-ec2/capistrano.rb b/lib/cap-ec2/capistrano.rb index 09b22f1..e2c0f96 100644 --- a/lib/cap-ec2/capistrano.rb +++ b/lib/cap-ec2/capistrano.rb @@ -21,7 +21,7 @@ def ec2_handler def ec2_role(name, options={}) ec2_handler.get_servers_for_role(options.fetch(:roles, name)).each do |roles, servers| servers.each do |server| - env.role(name, CapEC2::Utils.contact_point(server), options_with_instance_id(options, server)) + env.role(name, CapEC2::Utils.contact_point(server), options_with_instance_id(options, server, roles)) end end end @@ -32,8 +32,8 @@ def env private - def options_with_instance_id(options, server) - options.merge({aws_instance_id: server.instance_id}) + def options_with_instance_id(options, server, extra_roles) + options.merge({aws_instance_id: server.instance_id, extra_roles: Array(extra_roles).map(&:to_sym)}) end end diff --git a/lib/cap-ec2/ec2-handler.rb b/lib/cap-ec2/ec2-handler.rb index 2b8c303..2d837a0 100644 --- a/lib/cap-ec2/ec2-handler.rb +++ b/lib/cap-ec2/ec2-handler.rb @@ -43,7 +43,7 @@ def instance_ids end def defined_roles - roles(:all).flat_map(&:roles_array).uniq.sort + roles(:all).flat_map {|i| i.roles_array | (i.properties.extra_roles || []) }.uniq.sort end def stage diff --git a/lib/cap-ec2/status-table.rb b/lib/cap-ec2/status-table.rb index 6f338f7..57c10bf 100644 --- a/lib/cap-ec2/status-table.rb +++ b/lib/cap-ec2/status-table.rb @@ -1,12 +1,12 @@ module CapEC2 class StatusTable include CapEC2::Utils - + def initialize(instances) @instances = instances output end - + def header_row [ bold("Num"), @@ -14,12 +14,13 @@ def header_row bold("ID"), bold("Type"), bold("DNS"), + bold("Internal"), bold("Zone"), bold("Roles"), bold("Stages") ] end - + def output table = Terminal::Table.new( :style => { @@ -42,6 +43,7 @@ def instance_to_row(instance, index) red(instance.id), cyan(instance.instance_type), bold(blue(CapEC2::Utils.contact_point(instance))), + bold(blue(instance.private_ip_address)), magenta(instance.availability_zone), yellow(instance.tags[roles_tag]), yellow(instance.tags[stages_tag])