leeroy_app 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a33c630bfff44d8f1fbaff8694c65891aef0f8c5
4
- data.tar.gz: ad0999e31aec974b08fb8f1e10c268b62a653004
3
+ metadata.gz: 0c6837848cfe4074d257010b7e9ee430844ab59b
4
+ data.tar.gz: 743dc38168b8eb748a440372aaa0ee5598c9daf3
5
5
  SHA512:
6
- metadata.gz: faf7735d2cdcd8f9cf9cb0e834210f465802fb614845bdca5c8ccd7bb1f3bd8da3d81cda343c036bfe2cf1488d32196c7b28ee6eb5d2c7dab40fc96aa2eedf0e
7
- data.tar.gz: a5c965a55dc5be2683f0f27e98405e7c200ef6f0566ef000b62e760d8150e3e58b57c2e4b74193fd697abfb35949e3c1dfc853adb932fc423ed4109a0065dddf
6
+ metadata.gz: 167b5061e5a7323724d11850d3468f6f9b09e3fe3d941729ab9122b22d3e257377bb1cacd53af7a4bc1d305b1c7269ed230eb6c842533e6ca03b48575428eaa8
7
+ data.tar.gz: db277e54f900b5e6acd2b50e525debabacf2f146ecf50352dac914c91523f2b69619f34cdca2910ad0c74be688452763aa2b606612fe0428c20accc689b09247
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # leeroy
1
+ # leeroy [![Gem Version](https://badge.fury.io/rb/leeroy_app.svg)](https://badge.fury.io/rb/leeroy_app) [![Code Climate](https://codeclimate.com/github/FitnessKeeper/leeroy/badges/gpa.svg)](https://codeclimate.com/github/FitnessKeeper/leeroy)
2
2
  o rly? ya rly!
3
3
 
4
4
  ## Installation/Configuration
data/lib/leeroy/app.rb CHANGED
@@ -8,6 +8,7 @@ require 'leeroy/task/instantiate'
8
8
  require 'leeroy/task/terminate'
9
9
  require 'leeroy/task/sleep'
10
10
  require 'leeroy/task/stub'
11
+ require 'leeroy/types/phase'
11
12
 
12
13
  include GLI::App
13
14
 
@@ -15,7 +16,7 @@ module Leeroy
15
16
  module App
16
17
 
17
18
  # constants
18
- VALID_PHASE = ['gold_master','application']
19
+ VALID_PHASE = Leeroy::Types::Phase::VALID_PHASE
19
20
 
20
21
  program_desc 'Automate tasks with Jenkins'
21
22
 
data/lib/leeroy/env.rb CHANGED
@@ -14,11 +14,13 @@ module Leeroy
14
14
 
15
15
  # constants
16
16
  S3_PREFIXES = {
17
- :secrets => 'secrets',
18
- :jenkins => 'jenkins',
19
17
  :builds => 'builds',
18
+ :fixtures => 'fixtures',
19
+ :jenkins => 'jenkins',
20
20
  :logs => 'logs',
21
+ :secrets => 'secrets',
21
22
  :semaphores => 'semaphores',
23
+ :sql => 'fixtures/sql',
22
24
  :tests => 'tests',
23
25
  }
24
26
 
@@ -38,7 +40,7 @@ module Leeroy
38
40
  'LEEROY_POLL_TIMEOUT' => '<number of seconds to wait between giving up on long-running AWS operations>',
39
41
  'LEEROY_PROVISIONING_TEMPLATE_PREFIX' => '<path on local filesystem to directory containing provisioning templates>',
40
42
  'LEEROY_S3_BUCKET' => '<name of bucket used as datastore>',
41
- 'LEEROY_PROVISIONING_TEMPLATE_PREFIX' => '<path on local filesystem to directory containing user-data templates>',
43
+ 'LEEROY_USER_DATA_PREFIX' => '<path on local filesystem to directory containing user-data scripts>',
42
44
  }
43
45
 
44
46
  ENV_EXTRAS = {
@@ -13,7 +13,7 @@ module Leeroy
13
13
  module AWS
14
14
  include Leeroy::Helpers
15
15
 
16
- attr :ec2, :s3
16
+ attr :ec2, :rds, :s3
17
17
 
18
18
  def initialize(*args, &block)
19
19
  super(*args, &block)
@@ -21,6 +21,7 @@ module Leeroy
21
21
  logger.debug "initializing AWS helpers"
22
22
 
23
23
  @ec2 = Aws::EC2::Client.new
24
+ @rds = Aws::RDS::Client.new
24
25
  @s3 = Aws::S3::Client.new
25
26
 
26
27
  logger.debug "AWS helpers initialized"
@@ -31,7 +32,6 @@ module Leeroy
31
32
  def ec2Request(method, params = {}, ec2 = self.ec2, options = self.options, global_options = self.global_options)
32
33
  begin
33
34
  logger.debug "constructing EC2 request for '#{method}'"
34
- logger.debug "params: #{params.inspect}"
35
35
 
36
36
  params_mash = Leeroy::Types::Mash.new(params)
37
37
  params = params_mash
@@ -40,8 +40,6 @@ module Leeroy
40
40
 
41
41
  params.dry_run = dry_run
42
42
 
43
- logger.debug "params: #{params.inspect}"
44
-
45
43
  resp = ec2.send(method.to_sym, params)
46
44
 
47
45
  logger.debug "resp: #{resp.inspect}"
@@ -207,7 +205,7 @@ module Leeroy
207
205
 
208
206
  resp = ec2Request(:describe_images, run_params)
209
207
 
210
- # now filter based on callback
208
+ # now filter based on callbacks
211
209
  resp.images.select {|x| selector.call(x)}.collect {|x| collector.call(x)}
212
210
 
213
211
  rescue Aws::EC2::Errors::DryRunOperation => e
@@ -219,30 +217,58 @@ module Leeroy
219
217
  end
220
218
  end
221
219
 
220
+ def getImageByName(image_name)
221
+ begin
222
+
223
+ raise "image_name parameter cannot be nil" if image_name.nil?
224
+
225
+ selector = lambda {|image| image.name == image_name}
226
+ collector = lambda {|image| image.image_id}
227
+
228
+ image_ids = filterImages(selector, collector)
229
+ logger.debug image_ids.inspect
230
+ logger.debug "image_name: #{image_name}"
231
+
232
+ image_ids[0]
233
+
234
+ rescue StandardError => e
235
+ raise e
236
+ end
237
+ end
238
+
239
+
222
240
  def getGoldMasterInstanceName(env_name = 'LEEROY_GOLD_MASTER_NAME')
223
241
  checkEnv(env_name)
224
242
  end
225
243
 
226
- def getApplicationInstanceName(index, env_app = 'LEEROY_APP_NAME', env_name = 'LEEROY_BUILD_TARGET')
227
- name_prefix = [checkEnv(env_app), checkEnv(env_name), index].join('-')
244
+ def getApplicationInstanceName(index = nil, env_app = 'LEEROY_APP_NAME', env_name = 'LEEROY_BUILD_TARGET')
245
+ name_prefix = [checkEnv(env_app), checkEnv(env_name)].join('-')
228
246
  logger.debug "name_prefix: #{name_prefix}"
229
247
 
230
248
  if index.nil?
231
- # determine the index by looking at existing images
232
- selector = lambda {|image| image.name =~ /^#{name_prefix}/}
233
- # and extract the names
234
- collector = lambda {|image| image.name}
235
-
236
- image_names = filterImages(selector, collector)
237
- logger.debug image_names.awesome_inspect
249
+ index = getApplicationImageIndex
238
250
  end
239
251
 
252
+ instance_name = [name_prefix, index].join('-')
253
+ logger.debug "instance_name: #{instance_name}"
254
+
255
+ instance_name
256
+
240
257
  end
241
258
 
242
259
  def getGoldMasterImageIndex(env_prefix = 'LEEROY_GOLD_MASTER_IMAGE_PREFIX')
243
260
  name_prefix = checkEnv(env_prefix)
244
- logger.debug "name_prefix: #{name_prefix}"
261
+ getMaxImageIndex(name_prefix)
262
+ end
245
263
 
264
+ def getApplicationImageIndex(env_build_target = 'LEEROY_BUILD_TARGET', env_app_name = 'LEEROY_APP_NAME')
265
+ app_name = checkEnv(env_app_name)
266
+ build_target = checkEnv(env_build_target)
267
+ name_prefix = [app_name, build_target].join('-')
268
+ getMaxImageIndex(name_prefix)
269
+ end
270
+
271
+ def getMaxImageIndex(name_prefix)
246
272
  # determine the index by looking at existing images
247
273
  selector = lambda {|image| image.name =~ /^#{name_prefix}/}
248
274
  # and extract the names
@@ -255,13 +281,54 @@ module Leeroy
255
281
  end
256
282
  end
257
283
 
258
- latest_image = image_numbers.sort.compact.uniq.pop
284
+ latest_image = image_numbers.sort.compact.uniq.pop || 1
259
285
  logger.debug "latest_image: #{latest_image}"
260
286
 
261
287
  latest_image
262
288
 
263
289
  end
264
290
 
291
+ # RDS
292
+
293
+ def rdsRequest(method, params = {}, rds = self.rds, options = self.options, global_options = self.global_options)
294
+ begin
295
+ logger.debug "constructing RDS request for '#{method}'"
296
+
297
+ params_mash = Leeroy::Types::Mash.new(params)
298
+ params = params_mash
299
+
300
+ logger.debug "params: #{params.inspect}"
301
+
302
+ resp = rds.send(method.to_sym, params)
303
+
304
+ logger.debug "resp: #{resp.inspect}"
305
+
306
+ resp
307
+
308
+ rescue StandardError => e
309
+ raise e
310
+ end
311
+ end
312
+
313
+ def getRDSInstanceEndpoint(instancename, rds = self.rds)
314
+ begin
315
+ logger.debug "getting DB Instance Endpoint for '#{instancename}'"
316
+
317
+ resp = rdsRequest(:describe_db_instances, {:db_instance_identifier => instancename})
318
+ db_instances = resp.db_instances
319
+ logger.debug "db_instances: #{db_instances.inspect}"
320
+
321
+ db_instances[0].endpoint.address
322
+
323
+ rescue Aws::EC2::Errors::DryRunOperation => e
324
+ logger.info e.message
325
+ "DRYRUN_DUMMY_VALUE: #{self.class.to_s}"
326
+
327
+ rescue StandardError => e
328
+ raise e
329
+ end
330
+ end
331
+
265
332
  # S3
266
333
 
267
334
  def s3Request(method, params = {}, s3 = self.s3, options = self.options, global_options = self.global_options)
@@ -0,0 +1,81 @@
1
+ # Helper methods for managing inventory (images, instances, etc.)
2
+ #
3
+ require 'leeroy/helpers'
4
+ require 'leeroy/helpers/aws'
5
+ require 'leeroy/helpers/logging'
6
+
7
+ module Leeroy
8
+ module Helpers
9
+ module Inventory
10
+ include Leeroy::Helpers::AWS
11
+ include Leeroy::Helpers::Logging
12
+
13
+ # determine the name of an AMI to use in creating an instance
14
+ def genImageName(phase = nil, state = self.state, options = self.options)
15
+ begin
16
+ # extract phase from state if not provided
17
+ phase = state.phase if phase.nil?
18
+
19
+ raise "no phase provided in state data or as param, exiting." if phase.nil?
20
+
21
+ # were we given an app_name?
22
+ app_name = state.app_name? ? state.app_name : checkEnv('LEEROY_APP_NAME')
23
+ logger.debug "app_name: #{app_name}"
24
+
25
+ # build target depends on phase
26
+ build_target = case phase
27
+ when 'gold_master'
28
+ 'master'
29
+ when 'application'
30
+ checkEnv('LEEROY_BUILD_TARGET')
31
+ else
32
+ raise "unable to build target for phase"
33
+ end
34
+
35
+ # were we given an image index?
36
+ index = genImageIndex(state, self.env, self.ec2, options).to_s
37
+ logger.debug "index: #{index}"
38
+
39
+ image_name = [app_name, build_target, index].join('-')
40
+
41
+ logger.debug "image_name: #{image_name}"
42
+
43
+ image_name
44
+
45
+ rescue StandardError => e
46
+ raise e
47
+ end
48
+ end
49
+
50
+ def genImageIndex(state = self.state, env = self.env, ec2 = self.ec2, options = self.options)
51
+ begin
52
+ index = options[:index]
53
+
54
+ if index
55
+ logger.debug "index provided: #{index}"
56
+ else
57
+ logger.debug "index not provided, calculating"
58
+ phase = state.phase
59
+
60
+ index = case phase
61
+ when 'gold_master'
62
+ getGoldMasterImageIndex.to_i + 1
63
+ when 'application'
64
+ getGoldMasterImageIndex.to_i
65
+ else
66
+ raise "unable to determine image index for phase '#{phase.to_s}'"
67
+ end
68
+ end
69
+
70
+ logger.debug "index: #{index}"
71
+
72
+ index
73
+
74
+ rescue StandardError => e
75
+ raise e
76
+ end
77
+ end
78
+
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,23 @@
1
+ require 'leeroy/helpers'
2
+
3
+ module Leeroy
4
+ module Helpers
5
+ module Template
6
+ include Leeroy::Helpers
7
+
8
+ def renderTemplate(template, b = binding)
9
+ begin
10
+ logger.debug "processing template '#{template}'"
11
+
12
+ # run the ERB renderer in a separate thread, restricted
13
+ # http://www.stuartellis.eu/articles/erb/
14
+ ERB.new(File.read(template), 0).result(binding)
15
+
16
+ rescue StandardError => e
17
+ raise e
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -21,26 +21,14 @@ module Leeroy
21
21
  def initialize(params = {})
22
22
  begin
23
23
  @global_options = params.fetch(:global_options, {})
24
- logger.debug("global_options: #{self.global_options.to_s}")
25
-
26
- logger.debug("setting options")
27
24
  @options = params.fetch(:options, {})
28
- logger.debug("options: #{self.options.to_s}")
29
-
30
- logger.debug("setting args")
31
25
  @args = params.fetch(:args, {})
32
- logger.debug("args: #{self.args.to_s}")
33
26
 
34
- logger.debug("setting env")
35
27
  @env = Leeroy::Env.new({}, params.fetch(:env, ENV))
36
- logger.debug("env: #{self.env.to_s}")
37
28
 
38
- logger.debug("setting state")
39
29
  @state = Leeroy::State.new(state_from_pipe(params.fetch(:state, {})))
40
30
  rotate_task_metadata
41
- logger.debug("state: #{self.state}")
42
31
 
43
- logger.debug("base initialization of #{self.class.to_s} complete")
44
32
  rescue StandardError => e
45
33
  raise e
46
34
  end
@@ -51,6 +39,7 @@ module Leeroy
51
39
  self.logger.info("performing #{self.class.to_s}")
52
40
  self.logger.debug("args: #{args.inspect}")
53
41
  self.logger.debug("options: #{options.inspect}")
42
+ self.logger.debug("global_options: #{global_options.inspect}")
54
43
 
55
44
  rescue StandardError => e
56
45
  raise e
@@ -1,6 +1,7 @@
1
1
  require 'leeroy'
2
2
  require 'leeroy/task'
3
3
  require 'leeroy/helpers/aws'
4
+ require 'leeroy/helpers/inventory'
4
5
  require 'leeroy/helpers/polling'
5
6
  require 'leeroy/types/image'
6
7
  require 'leeroy/types/phase'
@@ -9,6 +10,7 @@ module Leeroy
9
10
  module Task
10
11
  class Image < Leeroy::Task::Base
11
12
  include Leeroy::Helpers::AWS
13
+ include Leeroy::Helpers::Inventory
12
14
  include Leeroy::Helpers::Polling
13
15
 
14
16
  def perform(args = self.args, options = self.options, global_options = self.global_options)
@@ -90,18 +92,8 @@ module Leeroy
90
92
  logger.debug "instance_id: #{instance_id}"
91
93
  image_params.instance_id = instance_id
92
94
 
93
- # were we given an app_name?
94
- app_name = state.app_name? ? state.app_name : checkEnv('LEEROY_APP_NAME')
95
- logger.debug "app_name: #{app_name}"
96
-
97
- # were we given an image index?
98
- index = _genImageIndex(state, env, ec2, options).to_s
99
- logger.debug "index: #{index}"
100
-
101
- # build target depends on phase
102
- build_target = phase == 'gold_master' ? 'master' : checkEnv('LEEROY_BUILD_TARGET')
103
-
104
- image_params.name = [app_name, build_target, index].join('-')
95
+ # generate image name based on state data
96
+ image_params.name = genImageName(phase, state)
105
97
 
106
98
  image_params
107
99
 
@@ -110,17 +102,6 @@ module Leeroy
110
102
  end
111
103
  end
112
104
 
113
- def _genImageIndex(state = self.state, env = self.env, ec2 = self.ec2, options = self.options)
114
- begin
115
- logger.debug "determining gold master instance ID"
116
-
117
- options[:index] or getGoldMasterImageIndex.to_i + 1
118
-
119
- rescue StandardError => e
120
- raise e
121
- end
122
- end
123
-
124
105
  end
125
106
  end
126
107
  end
@@ -1,13 +1,17 @@
1
1
  require 'leeroy'
2
2
  require 'leeroy/task'
3
3
  require 'leeroy/helpers/aws'
4
+ require 'leeroy/helpers/inventory'
4
5
  require 'leeroy/helpers/polling'
6
+ require 'leeroy/helpers/template'
5
7
 
6
8
  module Leeroy
7
9
  module Task
8
10
  class Instantiate < Leeroy::Task::Base
9
11
  include Leeroy::Helpers::AWS
12
+ include Leeroy::Helpers::Inventory
10
13
  include Leeroy::Helpers::Polling
14
+ include Leeroy::Helpers::Template
11
15
 
12
16
  def perform(args = self.args, options = self.options, global_options = self.global_options)
13
17
  begin
@@ -88,22 +92,7 @@ module Leeroy
88
92
  def _readSemaphore(phase)
89
93
  begin
90
94
  template = File.join(checkEnv('LEEROY_PROVISIONING_TEMPLATE_PREFIX'), "#{phase}.erb")
91
- logger.debug "processing template '#{template}'"
92
-
93
- # this is heinous
94
- # http://stackoverflow.com/a/22777806/17597
95
- rendered = String.new
96
-
97
- begin
98
- old_stdout = $stdout
99
- $stdout = StringIO.new('','w')
100
- ERB.new(File.read(template)).run
101
- rendered = $stdout.string
102
- ensure
103
- $stdout = old_stdout
104
- end
105
-
106
- rendered
95
+ renderTemplate(template, binding)
107
96
 
108
97
  rescue StandardError => e
109
98
  raise e
@@ -166,15 +155,18 @@ module Leeroy
166
155
  phase = options[:phase]
167
156
  logger.debug "phase is #{phase}"
168
157
 
158
+ instance_params.phase = phase
159
+
169
160
  # AMI id depends on phase
170
- if phase == 'gold_master'
171
- image_id = checkEnv('LEEROY_AWS_LINUX_AMI')
172
- elsif phase == 'application'
173
- image_id = state.imageid
161
+ image_id = case phase
162
+ when 'gold_master'
163
+ checkEnv('LEEROY_AWS_LINUX_AMI')
164
+ when 'application'
165
+ state.imageid || getImageByName(genImageName('gold_master'))
166
+ else
167
+ nil
174
168
  end
175
169
 
176
- instance_params.phase = phase
177
-
178
170
  raise "unable to determine image ID for phase '#{phase}'" if image_id.nil?
179
171
 
180
172
  instance_params.image_id = image_id
@@ -1,6 +1,10 @@
1
+ require 'leeroy/helpers/logging'
2
+
1
3
  module Leeroy
2
4
  module Types
3
5
  class Phase < String
6
+ include Leeroy::Helpers::Logging
7
+
4
8
  VALID_PHASE = ['gold_master', 'application']
5
9
 
6
10
  def initialize(*args, &block)
@@ -10,6 +14,9 @@ module Leeroy
10
14
  phase = self.to_s
11
15
  raise "invalid value for phase: '#{phase}'" unless VALID_PHASE.include?(phase)
12
16
 
17
+ rescue TypeError => e
18
+ raise "invalid value for phase: #{e.message}"
19
+
13
20
  rescue StandardError => e
14
21
  raise e
15
22
  end
@@ -6,7 +6,7 @@ module Leeroy
6
6
  module Types
7
7
  class UserData < Leeroy::Types::PackedString
8
8
  def encoded_for_ec2(input = self.to_s)
9
- Base64.urlsafe_encode64(input)
9
+ Base64.encode64(input)
10
10
  end
11
11
  end
12
12
  end
@@ -1,3 +1,3 @@
1
1
  module Leeroy
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leeroy_app
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Huff
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-02 00:00:00.000000000 Z
11
+ date: 2016-03-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aruba
@@ -276,9 +276,11 @@ files:
276
276
  - lib/leeroy/helpers/aws.rb
277
277
  - lib/leeroy/helpers/dumpable.rb
278
278
  - lib/leeroy/helpers/env.rb
279
+ - lib/leeroy/helpers/inventory.rb
279
280
  - lib/leeroy/helpers/logging.rb
280
281
  - lib/leeroy/helpers/polling.rb
281
282
  - lib/leeroy/helpers/state.rb
283
+ - lib/leeroy/helpers/template.rb
282
284
  - lib/leeroy/state.rb
283
285
  - lib/leeroy/task.rb
284
286
  - lib/leeroy/task/base.rb