Class: Broadside::EcsManager

Inherits:
Object
  • Object
show all
Extended by:
LoggingUtils
Defined in:
lib/broadside/ecs/ecs_manager.rb

Constant Summary collapse

DEFAULT_DESIRED_COUNT =
0

Class Method Summary collapse

Class Method Details

.check_service_and_task_definition_state!(target) ⇒ Object



132
133
134
135
# File 'lib/broadside/ecs/ecs_manager.rb', line 132

def check_service_and_task_definition_state!(target)
  check_task_definition_state!(target)
  check_service_state!(target)
end

.check_service_state!(target) ⇒ Object



143
144
145
146
147
# File 'lib/broadside/ecs/ecs_manager.rb', line 143

def check_service_state!(target)
  unless service_exists?(target.cluster, target.family)
    raise Error, "No service for '#{target.family}'! Please bootstrap or manually configure one."
  end
end

.check_task_definition_state!(target) ⇒ Object



137
138
139
140
141
# File 'lib/broadside/ecs/ecs_manager.rb', line 137

def check_task_definition_state!(target)
  unless get_latest_task_definition_arn(target.family)
    raise Error, "No task definition for '#{target.family}'! Please bootstrap or manually configure one."
  end
end

.create_service(cluster, name, service_config = {}) ⇒ Object



17
18
19
20
21
22
23
24
25
26
# File 'lib/broadside/ecs/ecs_manager.rb', line 17

def create_service(cluster, name, service_config = {})
  ecs.create_service(
    {
      cluster: cluster,
      desired_count: DEFAULT_DESIRED_COUNT,
      service_name: name,
      task_definition: name
    }.deep_merge(service_config)
  )
end

.current_service_scale(target) ⇒ Object



149
150
151
152
# File 'lib/broadside/ecs/ecs_manager.rb', line 149

def current_service_scale(target)
  check_service_state!(target)
  EcsManager.ecs.describe_services(cluster: target.cluster, services: [target.family]).services.first[:desired_count]
end

.deregister_last_n_tasks_definitions(name, count) ⇒ Object

removes latest n task definitions



29
30
31
32
33
34
# File 'lib/broadside/ecs/ecs_manager.rb', line 29

def deregister_last_n_tasks_definitions(name, count)
  get_task_definition_arns(name).last(count).each do |arn|
    ecs.deregister_task_definition(task_definition: arn)
    debug "Deregistered #{arn}"
  end
end

.ecsObject



8
9
10
11
12
13
14
15
# File 'lib/broadside/ecs/ecs_manager.rb', line 8

def ecs
  @ecs_client ||= Aws::ECS::Client.new(
    region: Broadside.config.aws.region,
    credentials: Broadside.config.aws.credentials,
    logger: Broadside.config.logger,
    log_formatter: Aws::Log::Formatter.colored
  )
end

.get_latest_task_definition(name) ⇒ Object



36
37
38
39
# File 'lib/broadside/ecs/ecs_manager.rb', line 36

def get_latest_task_definition(name)
  return nil unless (arn = get_latest_task_definition_arn(name))
  ecs.describe_task_definition(task_definition: arn).task_definition.to_h
end

.get_latest_task_definition_arn(name) ⇒ Object



41
42
43
# File 'lib/broadside/ecs/ecs_manager.rb', line 41

def get_latest_task_definition_arn(name)
  get_task_definition_arns(name).last
end

.get_running_instance_ips(cluster, family, task_arns = nil) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/broadside/ecs/ecs_manager.rb', line 51

def get_running_instance_ips(cluster, family, task_arns = nil)
  task_arns = task_arns ? Array.wrap(task_arns) : get_task_arns(cluster, family)
  return [] if task_arns.empty?

  tasks = ecs.describe_tasks(cluster: cluster, tasks: task_arns).tasks
  container_instances = ecs.describe_container_instances(
    cluster: cluster,
    container_instances: tasks.map(&:container_instance_arn)
  ).container_instances

  ec2_instance_ids = container_instances.map(&:ec2_instance_id)
  reservations = ec2_client.describe_instances(instance_ids: ec2_instance_ids).reservations

  reservations.map(&:instances).flatten.map(&:private_ip_address)
end

.get_running_instance_ips!(cluster, family, task_arns = nil) ⇒ Object

Raises:



45
46
47
48
49
# File 'lib/broadside/ecs/ecs_manager.rb', line 45

def get_running_instance_ips!(cluster, family, task_arns = nil)
  ips = get_running_instance_ips(cluster, family, task_arns)
  raise Error, "No running tasks found for '#{family}' on cluster '#{cluster}'!" if ips.empty?
  ips
end

.get_task_arns(cluster, family, filter = {}) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/broadside/ecs/ecs_manager.rb', line 67

def get_task_arns(cluster, family, filter = {})
  options = {
    cluster: cluster,
    # Strange AWS restriction requires absence of family if service_name specified
    family: filter[:service_name] ? nil : family,
    desired_status: filter[:desired_status],
    service_name: filter[:service_name],
    started_by: filter[:started_by]
  }.reject { |_, v| v.nil? }

  all_results(:list_tasks, :task_arns, options)
end

.get_task_definition_arns(family) ⇒ Object



80
81
82
# File 'lib/broadside/ecs/ecs_manager.rb', line 80

def get_task_definition_arns(family)
  all_results(:list_task_definitions, :task_definition_arns, { family_prefix: family })
end

.get_task_exit_status(cluster, task_arn, name) ⇒ Object



84
85
86
87
88
89
90
91
92
# File 'lib/broadside/ecs/ecs_manager.rb', line 84

def get_task_exit_status(cluster, task_arn, name)
  task = ecs.describe_tasks(cluster: cluster, tasks: [task_arn]).tasks.first
  container = task.containers.select { |c| c.name == name }.first

  {
    exit_code: container.exit_code,
    reason: container.reason
  }
end

.list_services(cluster) ⇒ Object



98
99
100
# File 'lib/broadside/ecs/ecs_manager.rb', line 98

def list_services(cluster)
  all_results(:list_services, :service_arns, { cluster: cluster })
end

.list_task_definition_familiesObject



94
95
96
# File 'lib/broadside/ecs/ecs_manager.rb', line 94

def list_task_definition_families
  all_results(:list_task_definition_families, :families)
end

.run_task(cluster, name, command, options = {}) ⇒ Object

Raises:

  • (ArgumentError)


102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/broadside/ecs/ecs_manager.rb', line 102

def run_task(cluster, name, command, options = {})
  raise ArgumentError, "command: '#{command}' must be an array" unless command.is_a?(Array)

  response = ecs.run_task(
    cluster: cluster,
    task_definition: get_latest_task_definition_arn(name),
    overrides: {
      container_overrides: [
        {
          name: name,
          command: command
        }
      ]
    },
    count: 1,
    started_by: ((options[:started_by] ? "#{options[:started_by]}:" : '') + command.join(' '))[0...36]
  )

  unless response.successful? && response.tasks.try(:[], 0)
    raise EcsError, "Failed to run task '#{command.join(' ')}'\n#{response.pretty_inspect}"
  end

  response
end

.service_exists?(cluster, family) ⇒ Boolean

Returns:

  • (Boolean)


127
128
129
130
# File 'lib/broadside/ecs/ecs_manager.rb', line 127

def service_exists?(cluster, family)
  services = ecs.describe_services(cluster: cluster, services: [family])
  services.failures.empty? && services.services.any?
end