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



50
51
52
53
# File 'lib/movable_ink/aws/ec2.rb', line 50

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



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

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



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

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

#default_filter ⇒ Object



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

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_ips ⇒ Object



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

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

#instance_id ⇒ Object



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

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:, region: my_region, availability_zone: nil) ⇒ Object



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

def instance_ip_addresses_by_role(role:, region: my_region, availability_zone: nil)
  private_ip_addresses(instances(role: role, region: region, availability_zone: availability_zone))
end

#instance_ip_addresses_by_role_ordered(role:, region: my_region) ⇒ Object



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

def instance_ip_addresses_by_role_ordered(role:, region: my_region)
  instances = instances(role: role, region: region)
  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

#instances(role:, region: my_region, availability_zone: nil) ⇒ Object



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

def instances(role:, region: my_region, availability_zone: nil)
  role_pattern = mi_env == 'production' ? "^#{role}$" : "^*#{role}*$"
  role_pattern = role_pattern.gsub('**','*').gsub('*','.*')
  instances = all_instances(region: region).select { |instance|
    instance.tags.detect { |tag|
      tag.key == 'mi:roles'&&
        Regexp.new(role_pattern).match(tag.value) &&
        !tag.value.include?('decommissioned')
    }
  }
  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



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

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_env ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/movable_ink/aws/ec2.rb', line 13

def load_mi_env
  run_with_backoff(quiet: true) do
    begin
      ec2.describe_tags(filters: [
            {
              name: 'resource-id',
              values: [instance_id]
            }
          ])
        .tags
        .detect { |tag| tag.key == 'mi:env' }
        .value
    rescue NoMethodError
      raise MovableInk::AWS::Errors::NoEnvironmentTagError
    end
  end
end

#me ⇒ Object



92
93
94
# File 'lib/movable_ink/aws/ec2.rb', line 92

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

#mi_env ⇒ Object



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



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

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

#private_ipv4 ⇒ Object



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

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



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

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_host ⇒ Object



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

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

#thopter ⇒ Object



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

def thopter
  private_ip_addresses(thopter_instance).first
end

#thopter_filter ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/movable_ink/aws/ec2.rb', line 31

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

#thopter_instance ⇒ Object



46
47
48
# File 'lib/movable_ink/aws/ec2.rb', line 46

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

#unassigned_elastic_ips ⇒ Object



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

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