Class: Rebi::Environment

Inherits:
Object
  • Object
show all
Defined in:
lib/rebi/environment.rb

Constant Summary collapse

RESPONSES =
{
    'event.createstarting': 'createEnvironment is starting.',
    'event.terminatestarting': 'terminateEnvironment is starting.',
    'event.updatestarting': 'Environment update is starting.',
    'event.redmessage': 'Environment health has been set to RED',
    'event.commandfailed': 'Command failed on instance',
    'event.launchfailed': 'Failed to launch',
    'event.deployfailed': 'Failed to deploy application.',
    'event.redtoyellowmessage': 'Environment health has transitioned from YELLOW to RED',
    'event.yellowmessage': 'Environment health has been set to YELLOW',
    'event.greenmessage': 'Environment health has been set to GREEN',
    'event.launchsuccess': 'Successfully launched environment:',
    'event.launchbad': 'Create environment operation is complete, but with errors',
    'event.updatebad': 'Update environment operation is complete, but with errors.',
    'git.norepository': 'Error: Not a git repository (or any of the parent directories): .git',
    'env.updatesuccess': 'Environment update completed successfully.',
    'env.cnamenotavailable': 'DNS name \([^ ]+\) is not available.',
    'env.nameexists': 'Environment [^ ]+ already exists.',
    'app.deletesuccess': 'The application has been deleted successfully.',
    'app.exists': 'Application {app-name} already exists.',
    'app.notexists': 'No Application named {app-name} found.',
    'logs.pulled': 'Pulled logs for environment instances.',
    'logs.successtail': 'Successfully finished tailing',
    'logs.successbundle': 'Successfully finished bundling',
    'env.terminated': 'terminateEnvironment completed successfully.',
    'env.invalidstate': 'Environment named {env-name} is in an invalid state for this operation. Must be Ready.',
    'loadbalancer.notfound': 'There is no ACTIVE Load Balancer named',
    'ec2.sshalreadyopen': 'the specified rule "peer: 0.0.0.0/0, TCP, from port: 22, to port: 22,',
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(stage_name, env_name, client = Rebi.client) ⇒ Environment

Returns a new instance of Environment.



44
45
46
47
48
49
50
51
# File 'lib/rebi/environment.rb', line 44

def initialize stage_name, env_name, client=Rebi.client
  @stage_name = stage_name
  @env_name = env_name
  @client = client
  @config = Rebi.config.environment(stage_name, env_name)
  @app_name = @config.app_name
  @api_data
end

Instance Attribute Details

#api_dataObject

Returns the value of attribute api_data.



10
11
12
# File 'lib/rebi/environment.rb', line 10

def api_data
  @api_data
end

#app_nameObject (readonly)

Returns the value of attribute app_name.



4
5
6
# File 'lib/rebi/environment.rb', line 4

def app_name
  @app_name
end

#clientObject

Returns the value of attribute client.



10
11
12
# File 'lib/rebi/environment.rb', line 10

def client
  @client
end

#configObject (readonly)

Returns the value of attribute config.



4
5
6
# File 'lib/rebi/environment.rb', line 4

def config
  @config
end

#env_nameObject (readonly)

Returns the value of attribute env_name.



4
5
6
# File 'lib/rebi/environment.rb', line 4

def env_name
  @env_name
end

#nameObject (readonly)

Returns the value of attribute name.



4
5
6
# File 'lib/rebi/environment.rb', line 4

def name
  @name
end

#stage_nameObject (readonly)

Returns the value of attribute stage_name.



4
5
6
# File 'lib/rebi/environment.rb', line 4

def stage_name
  @stage_name
end

Class Method Details

.all(client = Rebi.client) ⇒ Object

TODO



294
295
296
297
# File 'lib/rebi/environment.rb', line 294

def self.all client=Rebi.client
  client.describe_environments(application_name: app_name,
                               include_deleted: false).environments
end

.create(stage_name, env_name, version_label, client) ⇒ Object



285
286
287
288
289
290
291
# File 'lib/rebi/environment.rb', line 285

def self.create stage_name, env_name, version_label, client
  env =  new stage_name, env_name, client
  raise Rebi::Error::EnvironmentExisted.new if env.created?

  env.init version_label
  return env
end

.get(stage_name, env_name, client = Rebi.client) ⇒ Object



299
300
301
302
# File 'lib/rebi/environment.rb', line 299

def self.get stage_name, env_name, client=Rebi.client
  env = new stage_name, env_name, client
  return env.created? ? env : nil
end

Instance Method Details

#check_createdObject



104
105
106
107
# File 'lib/rebi/environment.rb', line 104

def check_created
  raise Rebi::Error::EnvironmentNotExisted.new("#{name} not exists") unless created?
  return created?
end

#check_created!Object

refresh data



110
111
112
113
# File 'lib/rebi/environment.rb', line 110

def check_created!
  refresh
  check_created
end

#cnameObject



57
58
59
# File 'lib/rebi/environment.rb', line 57

def cname
  created? ? api_data.cname : nil
end

#created?Boolean

Returns:

  • (Boolean)


115
116
117
# File 'lib/rebi/environment.rb', line 115

def created?
  !!api_data
end

#deploy(version_label, opts = {}) ⇒ Object



215
216
217
218
219
220
221
222
# File 'lib/rebi/environment.rb', line 215

def deploy version_label, opts={}
  request_id = if created?
    update version_label, opts
  else
    init version_label, opts
  end
  return request_id
end

#environment_variablesObject



96
97
98
99
100
101
102
# File 'lib/rebi/environment.rb', line 96

def environment_variables
  option_settings.select do |o|
      o[:namespace] == config.ns(:app_env)
  end.map do |o|
        [o[:option_name], o[:value]]
  end.to_h.with_indifferent_access
end

#events(start_time = Time.now, request_id = nil) ⇒ Object



150
151
152
153
154
155
156
# File 'lib/rebi/environment.rb', line 150

def events start_time=Time.now, request_id=nil
  client.describe_events({
    application_name: app_name,
    environment_name: name,
    start_time: start_time,
  }.merge( request_id ? {request_id: request_id} : {})).events
end

#gen_deploy_optsObject



267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/rebi/environment.rb', line 267

def gen_deploy_opts
  to_deploy = []
  to_remove = []
  config.opts_array.each do |o|
    o = o.deep_dup
    if o[:namespace] == config.ns(:app_env) && o[:value].blank?
      o.delete(:value)
      to_remove << o
      next
    end
    to_deploy << o
  end
  return {
    option_settings: to_deploy,
    options_to_remove:  to_remove,
  }
end

#healthObject



77
78
79
# File 'lib/rebi/environment.rb', line 77

def health
  check_created! && api_data.health
end

#idObject



65
66
67
# File 'lib/rebi/environment.rb', line 65

def id
  created? ? api_data.environment_id : nil
end

#in_updating?Boolean

Returns:

  • (Boolean)


73
74
75
# File 'lib/rebi/environment.rb', line 73

def in_updating?
  !!status.match("ing$")
end

#init(version_label, opts = {}) ⇒ Object



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/rebi/environment.rb', line 163

def init version_label, opts={}
  log("Creating new environment")
  start_time = Time.now
  self.api_data = client.create_environment({
    application_name: config.app_name,
    cname_prefix: config.cname_prefix,
    environment_name: config.name,
    version_label: version_label,
    tier: config.tier,
    description: config.description,
    option_settings: config.opts_array,
  }.merge(if(config.platform_arn)
    { platform_arn: config.platform_arn}
  else
    { solution_stack_name: config.solution_stack_name}
  end))
  request_id = events(start_time).select do |e|
    e.message.match(response_msgs('event.createstarting'))
  end.map(&:request_id).first
  return request_id
end

#log(mes) ⇒ Object



239
240
241
# File 'lib/rebi/environment.rb', line 239

def log mes
  Rebi.log(mes, name)
end

#option_settingsObject



81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/rebi/environment.rb', line 81

def option_settings
  check_created!
  client.describe_configuration_settings({
    application_name: app_name,
    environment_name: name
  }).configuration_settings.first.option_settings.map do |o|
    {
      namespace: o.namespace,
      value: o.value,
      resource_name: o.resource_name,
      option_name: o.option_name,
    }.with_indifferent_access
  end
end

#refreshObject



158
159
160
161
# File 'lib/rebi/environment.rb', line 158

def refresh
  self.api_data = nil
  return self
end

#response_msgs(key = nil) ⇒ Object



125
126
127
128
# File 'lib/rebi/environment.rb', line 125

def response_msgs key=nil
  @response_msgs ||= RESPONSES.with_indifferent_access
  return key ? @response_msgs[key] : @response_msgs
end

#statusObject



69
70
71
# File 'lib/rebi/environment.rb', line 69

def status
  check_created! && api_data.status
end

#success_message?(mes) ⇒ Boolean

Returns:

  • (Boolean)


243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/rebi/environment.rb', line 243

def success_message? mes
  return true if [
    'event.greenmessage',
    'event.launchsuccess',
    'logs.pulled',
    'env.terminated',
    'env.updatesuccess',
    'app.deletesuccess',
  ].map{|k| response_msgs(k)}.any?{|s| mes.match(s)}

  if [
        'event.redmessage',
        'event.launchbad',
        'event.updatebad',
        'event.commandfailed',
        'event.launchfailed',
        'event.deployfailed',
      ].map {|k| response_msgs(k)}.any? {|s| mes.match(s)}
    raise Rebi::Error::ServiceError.new(mes)
  end

  return false
end

#terminate!Object



224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/rebi/environment.rb', line 224

def terminate!
  check_created
  log("Start terminating")
  client.terminate_environment({
    environment_name: name,
    environment_id: id,
    })
  start_time = Time.now

  request_id = events(start_time).select do |e|
    e.message.match(response_msgs('event.updatestarting'))
  end.map(&:request_id).first
  return request_id
end

#update(version_label, opts = {}) ⇒ Object



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/rebi/environment.rb', line 185

def update version_label, opts={}
  raise Rebi::Error::EnvironmentInUpdating.new(name) if in_updating?
  log("Start updating")
  start_time = Time.now
  deploy_opts = gen_deploy_opts
  deploy_args = {
    application_name: config.app_name,
    environment_name: config.name,
    version_label: version_label,
    description: config.description,
    option_settings: deploy_opts[:option_settings],
    options_to_remove: deploy_opts[:options_to_remove],
  }

  if opts[:source_only]
    deploy_args.delete(:option_settings)
    deploy_args.delete(:options_to_remove)
  elsif opts[:settings_only]
    deploy_args.delete(:version_label)
  end

  self.api_data = client.update_environment(deploy_args)

  request_id = events(start_time).select do |e|
    e.message.match(response_msgs('event.updatestarting'))
  end.map(&:request_id).first

  return request_id
end

#version_labelObject



61
62
63
# File 'lib/rebi/environment.rb', line 61

def version_label
  created? ? api_data.version_label : nil
end

#watch_request(request_id) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/rebi/environment.rb', line 130

def watch_request request_id
  check_created!
  start = Time.now
  finished = false
  last_time = Time.now - 30.minute
  thread = Thread.new do
    while (start + Rebi.config.timeout) > Time.now && !finished
      events(last_time, request_id).reverse.each do |e|
        finished ||= success_message?(e.message)
        last_time = [last_time + 1.second, e.event_date + 1.second].max
        log(e.message)
      end
      sleep(5) unless finished
    end
    log ("Timeout") unless finished
  end
  thread.join
  return thread
end