Class: EngineYardCloudInstance

Inherits:
Object
  • Object
show all
Defined in:
lib/ey_cloud_awareness/engine_yard_cloud_instance.rb

Constant Summary collapse

HOMEDIR =
File.expand_path "~#{Etc.getpwuid.name}"
PRESENT_INSTANCE_ID_CACHE_PATH =
"#{HOMEDIR}/.ey_cloud_awareness/engine_yard_cloud_instance_id"
PRESENT_SECURITY_GROUP_CACHE_PATH =
"#{HOMEDIR}/.ey_cloud_awareness/engine_yard_cloud_security_group"
INSTANCES_CACHE_PATH =
"#{HOMEDIR}/.ey_cloud_awareness/engine_yard_cloud_ec2_instances.json"
DNA_PATH =
'/etc/chef/dna.json'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(instance_id) ⇒ EngineYardCloudInstance

Returns a new instance of EngineYardCloudInstance.



9
10
11
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 9

def initialize(instance_id)
  @instance_id = instance_id.to_s
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



41
42
43
44
45
46
47
48
49
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 41

def method_missing(name, *args, &block)
  if data and data.has_key?(name.to_s)
    data[name.to_s]
  elsif self.class.data and self.class.data.has_key?(name.to_s)
    self.class.data[name.to_s]
  else
    super
  end
end

Instance Attribute Details

#instance_idObject (readonly)

Returns the value of attribute instance_id.



8
9
10
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 8

def instance_id
  @instance_id
end

Class Method Details

.allObject

sabshere 9/21/10 from engineyard gem cli.rb def ssh_host_filter(opts)

return lambda {|instance| true }                                                if opts[:all]
return lambda {|instance| %w(solo app app_master    ).include?(instance.role) } if opts[:app_servers]
return lambda {|instance| %w(solo db_master db_slave).include?(instance.role) } if opts[:db_servers ]
return lambda {|instance| %w(solo db_master         ).include?(instance.role) } if opts[:db_master  ]
return lambda {|instance| %w(db_slave               ).include?(instance.role) } if opts[:db_slaves  ]
return lambda {|instance| %w(util                   ).include?(instance.role) &&
                                     opts[:utilities].include?(instance.name) } if opts[:utilities  ]
return lambda {|instance| %w(solo app_master        ).include?(instance.role) }

end



72
73
74
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 72

def all
  data['instances'].map { |instance_id, _| new instance_id }
end

.app_masterObject



96
97
98
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 96

def app_master
  find_all_by_instance_roles('app_master').first || find_all_by_instance_roles('solo').first
end

.app_serversObject



76
77
78
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 76

def app_servers
  find_all_by_instance_roles 'app', 'app_master', 'solo'
end

.as_jsonObject



145
146
147
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 145

def as_json(*)
  to_hash
end

.clearObject



116
117
118
119
120
121
122
123
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 116

def clear
  raise "[EY CLOUD AWARENESS GEM] Can't clear if we used from_hash" if proxy?
  self.data_cache = nil
  self.dna_cache = nil
  ec2_instances true
  present_security_group true
  present_instance_id true
end

.dataObject



125
126
127
128
129
130
131
132
133
134
135
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 125

def data
  return data_cache if data_cache.is_a? Hash
  raise "[EY CLOUD AWARENESS GEM] Can't calculate data if we used from_hash" if proxy?
  self.data_cache = Hash.new
  data_cache['instances'] = mixed_instances
  data_cache['environment'] = dna['engineyard']['environment'].except('instances', 'apps')
  data_cache['apps'] = dna['engineyard']['environment']['apps']
  data_cache['users'] = dna['users']
  data_cache['group_id'] = present_security_group
  data_cache
end

.db_masterObject



84
85
86
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 84

def db_master
  find_all_by_instance_roles('db_master').first || find_all_by_instance_roles('solo').first
end

.db_serversObject



80
81
82
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 80

def db_servers
  find_all_by_instance_roles 'db_master', 'db_slave', 'solo'
end

.db_slavesObject



88
89
90
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 88

def db_slaves
  find_all_by_instance_roles 'db_slave'
end

.dnaObject



181
182
183
184
185
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 181

def dna
  raise "[EY CLOUD AWARENESS GEM] Can't see DNA if we used from_hash" if proxy?
  raise "[EY CLOUD AWARENESS GEM] Can't read DNA from #{DNA_PATH}! You should put 'sudo chmod a+r /etc/chef/dna.json' your your before_migrate.rb!" unless File.readable?(DNA_PATH)
  self.dna_cache ||= ActiveSupport::JSON.decode(IO.read(DNA_PATH))
end

.dna_instancesObject



177
178
179
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 177

def dna_instances
  dna['engineyard']['environment']['instances']
end

.ec2_instances(refresh = false) ⇒ Object



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 216

def ec2_instances(refresh = false)
  raise "[EY CLOUD AWARENESS GEM] Can't call ec2_instances if we used from_hash" if proxy?
  if refresh or !File.readable?(INSTANCES_CACHE_PATH)
    ec2 = AWS::EC2::Base.new :access_key_id => dna['aws_secret_id'], :secret_access_key => dna['aws_secret_key']
    @_ec2_instances = ec2.describe_instances
    @_ec2_instances.recursive_kill_xml_item_keys!
    @_ec2_instances = @_ec2_instances['reservationSet'].select { |hash| present_security_group.include? hash['groupSet'].first['groupId'] }
    @_ec2_instances.map! { |hash| hash['instancesSet'].first.recursive_underscore_keys! }
    begin
      FileUtils.mkdir_p File.dirname(INSTANCES_CACHE_PATH)
      File.open(INSTANCES_CACHE_PATH, 'w') { |f| f.write @_ec2_instances.to_json }
    rescue Errno::EACCES
      $stderr.puts "[EY CLOUD AWARENESS GEM] Not caching instance data because #{INSTANCES_CACHE_PATH} can't be written to"
    end
  end
  @_ec2_instances ||= ActiveSupport::JSON.decode(IO.read(INSTANCES_CACHE_PATH))
end

.find_all_by_instance_roles(*args) ⇒ Object



112
113
114
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 112

def find_all_by_instance_roles(*args)
  data['instances'].select { |_, instance| Array.wrap(args).map(&:to_s).include? instance['role'] }.map { |instance_id, _| new instance_id }
end

.find_by_instance_id(instance_id) ⇒ Object



108
109
110
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 108

def find_by_instance_id(instance_id)
  new instance_id
end

.from_hash(hash) ⇒ Object



153
154
155
156
157
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 153

def from_hash(hash)
  self.proxy = true
  self.data_cache = hash
  self
end

.from_json(str) ⇒ Object



149
150
151
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 149

def from_json(str)
  from_hash ActiveSupport::JSON.decode(str)
end

.method_missing(name, *args, &block) ⇒ Object



159
160
161
162
163
164
165
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 159

def method_missing(name, *args, &block)
  if data and data.has_key?(name.to_s)
    data[name.to_s]
  else
    super
  end
end

.mixed_instancesObject



167
168
169
170
171
172
173
174
175
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 167

def mixed_instances
  ec2_instances.inject(Hash.new) do |memo, ec2_instance|
    instance_id = ec2_instance['instance_id']
    if dna_instance = dna_instances.detect { |i| i['id'] == instance_id }
      memo[instance_id] = dna_instance.merge ec2_instance
    end
    memo
  end
end

.presentObject



104
105
106
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 104

def present
  new present_instance_id
end

.present_instance_id(refresh = false) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 187

def present_instance_id(refresh = false)
  raise "[EY CLOUD AWARENESS GEM] Can't call present_instance_id if we used from_hash" if proxy?
  if refresh or !File.readable?(PRESENT_INSTANCE_ID_CACHE_PATH)
    @_present_instance_id = open("http://169.254.169.254/latest/meta-data/instance-id").gets
    begin
      FileUtils.mkdir_p File.dirname(PRESENT_INSTANCE_ID_CACHE_PATH)
      File.open(PRESENT_INSTANCE_ID_CACHE_PATH, 'w') { |f| f.write @_present_instance_id }
    rescue Errno::EACCES
      $stderr.puts "[EY CLOUD AWARENESS GEM] Not caching present instance because #{PRESENT_INSTANCE_ID_CACHE_PATH} can't be written to"
    end
  end
  @_present_instance_id ||= IO.read(PRESENT_INSTANCE_ID_CACHE_PATH)
end

.present_security_group(refresh = false) ⇒ Object



201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 201

def present_security_group(refresh = false)
  raise "[EY CLOUD AWARENESS GEM] Can't call present_security_group if we used from_hash" if proxy?
  if refresh or !File.readable?(PRESENT_SECURITY_GROUP_CACHE_PATH)
    @_present_security_group = open('http://169.254.169.254/latest/meta-data/security-groups').gets
    raise "[EY CLOUD AWARENESS GEM] Don't know how to deal with (possibly) multiple security group: #{@_present_security_group}" if @_present_security_group =~ /,;/
    begin
      FileUtils.mkdir_p File.dirname(PRESENT_SECURITY_GROUP_CACHE_PATH)
      File.open(PRESENT_SECURITY_GROUP_CACHE_PATH, 'w') { |f| f.write @_present_security_group }
    rescue Errno::EACCES
      $stderr.puts "[EY CLOUD AWARENESS GEM] Not caching present security group because #{PRESENT_SECURITY_GROUP_CACHE_PATH} can't be written to"
    end
  end
  @_present_security_group ||= IO.read(PRESENT_SECURITY_GROUP_CACHE_PATH)
end

.proxy?Boolean

Returns:

  • (Boolean)


137
138
139
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 137

def proxy?
  !!proxy
end

.to_hashObject



141
142
143
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 141

def to_hash
  data
end

.utilitiesObject



92
93
94
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 92

def utilities
  find_all_by_instance_roles 'util'
end

.with_rolesObject



100
101
102
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 100

def with_roles
  all.select { |i| i.role.present? }
end

Instance Method Details

#==(other) ⇒ Object



51
52
53
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 51

def ==(other)
  self.instance_id == other.instance_id
end

#appObject



23
24
25
26
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 23

def app
  raise "[EY CLOUD AWARENESS GEM] There is more than one app on this instance, so you can't use the #app method. Use #users.first (etc.) instead." if apps.length > 1
  apps.first
end

#as_jsonObject



33
34
35
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 33

def as_json(*)
  to_hash
end

#clearObject



13
14
15
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 13

def clear
  self.class.clear
end

#dataObject



37
38
39
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 37

def data
  self.class.data['instances'][instance_id]
end

#to_hashObject



17
18
19
20
21
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 17

def to_hash
  data.merge 'environment' => environment,
             'apps' => apps,
             'users' => users
end

#userObject



28
29
30
31
# File 'lib/ey_cloud_awareness/engine_yard_cloud_instance.rb', line 28

def user
  raise "[EY CLOUD AWARENESS GEM] There is more than one user on this instance, so you can't use the #user method. Use #users.first (etc.) instead." if users.length > 1
  users.first
end