require 'aws-sdk' require 'highline' # Context module Contexto # ECS class class Contextualize attr_reader :display, :cluster, :service def initialize(params = {}) @cluster = params.fetch(:cluster) if params[:cluster] @service = params.fetch(:service) if params[:service] @display = Contexto::Display.new end def run if (cluster || service) if (cluster && !service) select_services(cluster) elsif (cluster && service) select_tasks(cluster, service) end else select_clusters end end def select_clusters clusters = list_clusters cli.choose do |menu| puts "\n" menu.header = "Clusters " menu.prompt = "Please choose a cluster? " clusters.each do |cluster| c = esplit(cluster) menu.choice(c) { select_services(c) } end menu.choice(:nah) { return } end end def select_services(cluster) services = list_services(cluster) cli.choose do |menu| puts "\n" menu.header = "Services " menu.prompt = "Please choose a service? " services.each do |service| s = esplit(service) menu.choice(s) { select_tasks(cluster, s) } end menu.choice(:nah) { return } end end def select_tasks(cluster, service) show_tasks(cluster, service) task = describe_tasks(cluster, service) containers = task[:containers] cli.choose do |menu| puts "\n" menu.header = "Containers " menu.prompt = "Please choose a container? " containers.each do |container| menu.choice(container[:name]) { prompt_endpoint(cluster, service, container[:name]) } end menu.choice(:nah) { return } end end def show_tasks(cluster, service) task = describe_tasks(cluster, service) containers = task[:containers] ec2_instance_id = describe_container_instance(cluster, task[:container_instance_arn]) title = 'Containers' headings = %w(Container Status IP) rows = [] containers.each do |container| rows << [container[:name], container[:last_status], describe_instances(ec2_instance_id)] end @display.create_display(title, headings, rows) end def prompt_endpoint(cluster, service, container) cli.choose do |menu| puts "\n" menu.header = "Do you want to connect to container #{container}? " menu.prompt = "Please choose a connection type? " menu.choice(:console) { connect(cluster, service, container).console } menu.choice(:bash) { connect(cluster, service, container).bash } menu.choice(:ssh) { connect(cluster, service, container).ssh } menu.choice(:nah) { return } end end def connect(cluster, service, container) task = describe_tasks(cluster, service) ec2_instance_id = describe_container_instance(cluster, task[:container_instance_arn]) Contexto::SSH.new(describe_instances(ec2_instance_id), cluster, service, container) end def list_clusters resp = ecs_client.list_clusters resp.cluster_arns end def describe_clusters resp = ecs_client.describe_clusters( clusters: [ cluster ] ) resp.clusters[0].to_h end def list_services(cluster) resp = ecs_client.list_services( cluster: cluster ) resp.service_arns end def describe_services resp = ecs_client.describe_services( cluster: cluster, services: [ service ] ) resp.services[0].to_h end def describe_tasks(cluster, service) resp = ecs_client.describe_tasks( cluster: cluster, tasks: [task_arn(cluster, service)] ) resp.tasks[0].to_h end def task_arn(cluster, service) resp = ecs_client.list_tasks( cluster: cluster, service_name: service ) resp.task_arns[0] end def describe_container_instance(cluster, container_instance_arn) resp = ecs_client.describe_container_instances( cluster: cluster, container_instances: [ container_instance_arn ] ) resp.container_instances[0].ec2_instance_id end def describe_instances(ec2_instance_id) resp = ec2_client.describe_instances( instance_ids: [ec2_instance_id] ) resp.reservations[0].instances[0].private_ip_address end def esplit(name) name.split('/')[-1] end def cli HighLine.new end def region_name ENV['AWS_REGION'] || 'us-east-1' end def ecs_client Aws::ECS::Client.new(region: region_name.to_s) end def ec2_client Aws::EC2::Client.new(region: region_name.to_s) end end end