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



130
131
132
133
# File 'lib/broadside/ecs/ecs_manager.rb', line 130

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

.check_service_state!(target) ⇒ Object



141
142
143
144
145
# File 'lib/broadside/ecs/ecs_manager.rb', line 141

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



135
136
137
138
139
# File 'lib/broadside/ecs/ecs_manager.rb', line 135

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



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

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



147
148
149
150
# File 'lib/broadside/ecs/ecs_manager.rb', line 147

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



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

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
# 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
  )
end

.get_latest_task_definition(name) ⇒ Object



34
35
36
37
# File 'lib/broadside/ecs/ecs_manager.rb', line 34

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



39
40
41
# File 'lib/broadside/ecs/ecs_manager.rb', line 39

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

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



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

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:



43
44
45
46
47
# File 'lib/broadside/ecs/ecs_manager.rb', line 43

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



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

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



78
79
80
# File 'lib/broadside/ecs/ecs_manager.rb', line 78

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



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

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



96
97
98
# File 'lib/broadside/ecs/ecs_manager.rb', line 96

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

.list_task_definition_familiesObject



92
93
94
# File 'lib/broadside/ecs/ecs_manager.rb', line 92

def list_task_definition_families
  all_results(:list_task_definition_families, :families)
end

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

Raises:

  • (ArgumentError)


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

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)


125
126
127
128
# File 'lib/broadside/ecs/ecs_manager.rb', line 125

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