Module: MovableInk::AWS::EC2

Included in:
MovableInk::AWS
Defined in:
lib/movable_ink/aws/ec2.rb

Instance Method Summary collapse

Instance Method Details

#all_instances(region: my_region, no_filter: false) ⇒ Object



40
41
42
43
# File 'lib/movable_ink/aws/ec2.rb', line 40

def all_instances(region: my_region, no_filter: false)
  @all_instances ||= {}
  @all_instances[region] ||= load_all_instances(region, no_filter: no_filter)
end

#assign_ip_address(role:) ⇒ Object



161
162
163
164
165
166
167
168
# File 'lib/movable_ink/aws/ec2.rb', line 161

def assign_ip_address(role:)
  run_with_backoff do
    ec2.associate_address({
      instance_id: instance_id,
      allocation_id: available_elastic_ips(role: role).sample.allocation_id
    })
  end
end

#available_elastic_ips(role:) ⇒ Object



157
158
159
# File 'lib/movable_ink/aws/ec2.rb', line 157

def available_elastic_ips(role:)
  unassigned_elastic_ips.select { |address| address.tags.detect { |t| t.key == 'mi:roles' && t.value == role } }
end

#default_filterObject



45
46
47
48
49
50
51
52
53
54
# File 'lib/movable_ink/aws/ec2.rb', line 45

def default_filter
  [{
    name: 'instance-state-name',
    values: ['running']
  },
  {
    name: 'tag:mi:env',
    values: [mi_env]
  }]
end

#ec2(region: my_region) ⇒ Object



4
5
6
7
# File 'lib/movable_ink/aws/ec2.rb', line 4

def ec2(region: my_region)
  @ec2_client ||= {}
  @ec2_client[region] ||= Aws::EC2::Client.new(region: region)
end

#elastic_ipsObject



147
148
149
150
151
# File 'lib/movable_ink/aws/ec2.rb', line 147

def elastic_ips
  @all_elastic_ips ||= run_with_backoff do
    ec2.describe_addresses.addresses
  end
end

#instance_idObject



66
67
68
69
70
71
72
# File 'lib/movable_ink/aws/ec2.rb', line 66

def instance_id
  @instance_id ||= begin
    az = `ec2metadata --instance-id 2>/dev/null`.chomp
    raise(MovableInk::AWS::Errors::EC2Required) if az.empty?
    az
  end
end

#instance_ip_addresses_by_role(role:, exclude_roles: [], region: my_region, availability_zone: nil, exact_match: false) ⇒ Object



128
129
130
# File 'lib/movable_ink/aws/ec2.rb', line 128

def instance_ip_addresses_by_role(role:, exclude_roles: [], region: my_region, availability_zone: nil, exact_match: false)
  private_ip_addresses(instances(role: role, exclude_roles: exclude_roles, region: region, availability_zone: availability_zone, exact_match: exact_match))
end

#instance_ip_addresses_by_role_ordered(role:, exclude_roles: [], region: my_region, exact_match: false) ⇒ Object



132
133
134
135
136
137
# File 'lib/movable_ink/aws/ec2.rb', line 132

def instance_ip_addresses_by_role_ordered(role:, exclude_roles: [], region: my_region, exact_match: false)
  instances = instances(role: role, exclude_roles: exclude_roles, region: region, exact_match: exact_match)
  instances_in_my_az = instances.select { |instance| instance.placement.availability_zone == availability_zone }
  ordered_instances = instances_in_my_az.shuffle + (instances - instances_in_my_az).shuffle
  private_ip_addresses(ordered_instances)
end

#instance_tagsObject



74
75
76
77
78
79
80
# File 'lib/movable_ink/aws/ec2.rb', line 74

def instance_tags
  @instance_tags ||= run_with_backoff(quiet: true) do
    ec2.describe_tags({
      filters: [{ name: 'resource-id', values: [instance_id] } ]
    }).tags
  end
end

#instances(role:, exclude_roles: [], region: my_region, availability_zone: nil, exact_match: false) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/movable_ink/aws/ec2.rb', line 94

def instances(role:, exclude_roles: [], region: my_region, availability_zone: nil, exact_match: false)
  instances = all_instances(region: region).select { |instance|
    instance.tags.select{ |tag| tag.key == 'mi:roles' }.detect { |tag|
      roles = tag.value.split(/\s*,\s*/)
      if exact_match
        roles == [role]
      else
        exclude_roles.push('decommissioned')
        roles.include?(role) && !roles.any? { |role| exclude_roles.include?(role) }
      end
    }
  }

  if availability_zone
    instances.select { |instance|
      instance.placement.availability_zone == availability_zone
    }
  else
    instances
  end
end

#load_all_instances(region, no_filter: false, filter: nil) ⇒ Object



56
57
58
59
60
61
62
63
64
# File 'lib/movable_ink/aws/ec2.rb', line 56

def load_all_instances(region, no_filter: false, filter: nil)
  filters = no_filter ? nil : (filter || default_filter)

  run_with_backoff do
    ec2(region: region).describe_instances(filters: filters).flat_map do |resp|
      resp.reservations.flat_map(&:instances)
    end
  end
end

#load_mi_envObject



13
14
15
16
17
18
19
# File 'lib/movable_ink/aws/ec2.rb', line 13

def load_mi_env
  instance_tags
    .detect { |tag| tag.key == 'mi:env' }
    .value
rescue NoMethodError
  raise MovableInk::AWS::Errors::NoEnvironmentTagError
end

#meObject



90
91
92
# File 'lib/movable_ink/aws/ec2.rb', line 90

def me
  @me ||= all_instances.select{|instance| instance.instance_id == instance_id}
end

#mi_envObject



9
10
11
# File 'lib/movable_ink/aws/ec2.rb', line 9

def mi_env
  @mi_env ||= load_mi_env
end

#private_ip_addresses(instances) ⇒ Object



124
125
126
# File 'lib/movable_ink/aws/ec2.rb', line 124

def private_ip_addresses(instances)
  instances.map(&:private_ip_address)
end

#private_ipv4Object



82
83
84
85
86
87
88
# File 'lib/movable_ink/aws/ec2.rb', line 82

def private_ipv4
  @ipv4 ||= begin
    ipv4 = `ec2metadata --local-ipv4 2>/dev/null`.chomp
    raise(MovableInk::AWS::Errors::EC2Required) if ipv4.empty?
    ipv4
  end
end

#redis_by_role(role, port) ⇒ Object



139
140
141
142
143
144
145
# File 'lib/movable_ink/aws/ec2.rb', line 139

def redis_by_role(role, port)
  instance_ip_addresses_by_role(role: role)
    .shuffle
    .inject([]) { |redii, instance|
      redii.push({"host" => instance, "port" => port})
    }
end

#statsd_hostObject



120
121
122
# File 'lib/movable_ink/aws/ec2.rb', line 120

def statsd_host
  instance_ip_addresses_by_role(role: 'statsd', availability_zone: availability_zone).sample
end

#thopterObject



116
117
118
# File 'lib/movable_ink/aws/ec2.rb', line 116

def thopter
  private_ip_addresses(thopter_instance).first
end

#thopter_filterObject



21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/movable_ink/aws/ec2.rb', line 21

def thopter_filter
  [{
    name: 'tag:mi:roles',
    values: ['*thopter*']
  },
  {
    name: 'tag:mi:env',
    values: [mi_env]
  },
  {
    name: 'instance-state-name',
    values: ['running']
  }]
end

#thopter_instanceObject



36
37
38
# File 'lib/movable_ink/aws/ec2.rb', line 36

def thopter_instance
  @thopter_instance ||= load_all_instances('us-east-1', filter: thopter_filter)
end

#unassigned_elastic_ipsObject



153
154
155
# File 'lib/movable_ink/aws/ec2.rb', line 153

def unassigned_elastic_ips
  @unassigned_elastic_ips ||= elastic_ips.select { |address| address.association_id.nil? }
end