lambit 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.evnrc.example +1 -0
- data/.gitignore +18 -0
- data/.ruby-version.example +1 -0
- data/.travis.yml +0 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +11 -0
- data/LICENSE +20 -0
- data/README.md +74 -0
- data/Rakefile.rb +0 -0
- data/bin/lambit +91 -0
- data/lambit.gemspec +32 -0
- data/lambit.yml.example +96 -0
- data/lib/lambit.rb +6 -0
- data/lib/lambit/aws.rb +9 -0
- data/lib/lambit/aws/cloud_watch/alarm.rb +59 -0
- data/lib/lambit/aws/cloud_watch_events/rule.rb +62 -0
- data/lib/lambit/aws/lambda/function.rb +53 -0
- data/lib/lambit/aws/lambda/permission.rb +52 -0
- data/lib/lambit/aws/s3/bucket_notification_configuration.rb +81 -0
- data/lib/lambit/commands.rb +6 -0
- data/lib/lambit/commands/build.rb +128 -0
- data/lib/lambit/commands/common.rb +92 -0
- data/lib/lambit/commands/lambdas.rb +411 -0
- data/lib/lambit/commands/subcommand.rb +87 -0
- data/lib/lambit/common.rb +6 -0
- data/lib/lambit/common/config.rb +45 -0
- data/lib/lambit/common/hash_helper.rb +48 -0
- data/lib/lambit/common/logger.rb +24 -0
- data/lib/lambit/common/string_helper.rb +39 -0
- data/lib/lambit/version.rb +5 -0
- data/test/test_helper.rb +0 -0
- metadata +174 -0
@@ -0,0 +1,411 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
using Lambit::Common::StringHelper
|
4
|
+
using Lambit::Common::HashHelper
|
5
|
+
|
6
|
+
module Lambit::Commands
|
7
|
+
module Lambdas
|
8
|
+
def self.run(cmd, opts, args)
|
9
|
+
handler = handler_for cmd
|
10
|
+
output, exitstatus = handler.run opts, args
|
11
|
+
|
12
|
+
# Send Subcommand output to STDOUT if :debug
|
13
|
+
if Lambit.is_debug?
|
14
|
+
puts output unless output.nil? || output.empty?
|
15
|
+
end
|
16
|
+
|
17
|
+
# Return exit status
|
18
|
+
exitstatus
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.normalize_cmd(cmd)
|
22
|
+
cmd.to_s.downcase
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.handler_for(cmd)
|
26
|
+
if @handlers
|
27
|
+
@handlers[normalize_cmd(cmd)]
|
28
|
+
else
|
29
|
+
raise 'Uh Oh!'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.register_handler_for(cmd, handler=nil)
|
34
|
+
normalized_cmd = normalize_cmd(cmd)
|
35
|
+
handler = self.const_get(normalized_cmd.classify) if handler.nil?
|
36
|
+
|
37
|
+
@handlers ||= {}
|
38
|
+
@handlers[normalized_cmd] = handler
|
39
|
+
end
|
40
|
+
|
41
|
+
class Base < Lambit::Commands::Common::Base
|
42
|
+
attr_reader :tmpdir, :project_path, :config
|
43
|
+
attr_accessor :workspace
|
44
|
+
|
45
|
+
def initialize(opts, args)
|
46
|
+
super
|
47
|
+
@tmpdir = opts['tmpdir']
|
48
|
+
@workspace = opts['workspace']
|
49
|
+
@project_path = opts['project-path']
|
50
|
+
@config = Lambit.config
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Lambdas < Base
|
55
|
+
attr_reader :lambdas, :regexp
|
56
|
+
attr_accessor :lambda_config, :function_name, :index, :common_opts
|
57
|
+
|
58
|
+
def initialize(opts, args)
|
59
|
+
super
|
60
|
+
@regexp = opts['regexp']
|
61
|
+
@lambdas = self.config['lambdas']
|
62
|
+
end
|
63
|
+
|
64
|
+
def parse_hash(hash)
|
65
|
+
hash.update(hash) do |k, v|
|
66
|
+
if v.respond_to?(:has_key?)
|
67
|
+
parse_hash(v)
|
68
|
+
elsif v.respond_to?(:each)
|
69
|
+
v.flatten.each { |x| parse_hash(x) if x.respond_to?(:has_key?) }
|
70
|
+
else
|
71
|
+
if v.respond_to?(:to_str)
|
72
|
+
eval('"' + v + '"')
|
73
|
+
else
|
74
|
+
v
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def filter
|
81
|
+
if regexp.nil? || regexp.empty?
|
82
|
+
yield
|
83
|
+
elsif function_name.match Regexp.new(regexp)
|
84
|
+
yield
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def process
|
89
|
+
Lambit.logger.info "Processing Lambda: #{function_name}"
|
90
|
+
Lambit.logger.info "Using Workspace: #{workspace}"
|
91
|
+
end
|
92
|
+
|
93
|
+
def command
|
94
|
+
self.lambdas.each do |object|
|
95
|
+
@lambda_config = Marshal.load(Marshal.dump(object))
|
96
|
+
@function_name = @lambda_config['lambda_function']['function_name']
|
97
|
+
@workspace = File.join(tmpdir, Lambit.config['name'], function_name)
|
98
|
+
@common_opts = {'workspace' => workspace}
|
99
|
+
filter { process }
|
100
|
+
end
|
101
|
+
|
102
|
+
return '', self.exitstatus
|
103
|
+
end
|
104
|
+
|
105
|
+
protected
|
106
|
+
|
107
|
+
def graceful_continue
|
108
|
+
begin
|
109
|
+
yield
|
110
|
+
rescue Exception => e
|
111
|
+
if Lambit.is_debug?
|
112
|
+
Lambit.logger.error e
|
113
|
+
else
|
114
|
+
Lambit.logger.error e.message
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def verbose_msg_for(title, opts, args=nil)
|
120
|
+
Lambit.logger.info "#{title} with: #{opts}, #{args}" if Lambit.is_verbose?
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
class BuildLambdas < Lambdas
|
125
|
+
def create_workspace
|
126
|
+
# TODO: Create Workspaces (src and pkg)
|
127
|
+
opts = common_opts
|
128
|
+
args = []
|
129
|
+
title = "Create Workspace"
|
130
|
+
|
131
|
+
verbose_msg_for(title, opts, args)
|
132
|
+
Lambit::Commands::Common.run :create_workspace_command, common_opts, args unless Lambit.is_dry_run?
|
133
|
+
end
|
134
|
+
|
135
|
+
def package_templates
|
136
|
+
lambda_config['templates'].each do |tmpl_name, tmpl_config|
|
137
|
+
opts = common_opts.merge('project_path' => self.project_path)
|
138
|
+
args = [tmpl_name, tmpl_config]
|
139
|
+
title = "Create Templates"
|
140
|
+
|
141
|
+
verbose_msg_for(title, opts, args)
|
142
|
+
Lambit::Commands::Build.run :package_templates_command, opts, args unless Lambit.is_dry_run?
|
143
|
+
end if lambda_config['templates']
|
144
|
+
end
|
145
|
+
|
146
|
+
def package_pips
|
147
|
+
lambda_config['required_pips'].each do |required_pip|
|
148
|
+
opts = common_opts
|
149
|
+
args = [required_pip]
|
150
|
+
title = "Install pip"
|
151
|
+
|
152
|
+
verbose_msg_for(title, opts, args)
|
153
|
+
Lambit::Commands::Build.run :package_pip_command, opts, args unless Lambit.is_dry_run?
|
154
|
+
end if lambda_config['required_pips']
|
155
|
+
end
|
156
|
+
|
157
|
+
def package_source
|
158
|
+
opts = common_opts.merge('project_path' => self.project_path)
|
159
|
+
args = []
|
160
|
+
title = "Package Source"
|
161
|
+
|
162
|
+
verbose_msg_for(title, opts, args)
|
163
|
+
Lambit::Commands::Build.run :package_source_command, opts, args unless Lambit.is_dry_run?
|
164
|
+
end
|
165
|
+
|
166
|
+
def compress_package
|
167
|
+
opts = common_opts
|
168
|
+
args = []
|
169
|
+
title = "Compress Package"
|
170
|
+
|
171
|
+
verbose_msg_for(title, opts, args)
|
172
|
+
Lambit::Commands::Build.run :compress_package_command, common_opts, args unless Lambit.is_dry_run?
|
173
|
+
end
|
174
|
+
|
175
|
+
def process
|
176
|
+
super
|
177
|
+
# Create Workspace
|
178
|
+
graceful_continue { create_workspace }
|
179
|
+
|
180
|
+
# Package Templates
|
181
|
+
graceful_continue { package_templates }
|
182
|
+
|
183
|
+
# Package Pip(s)
|
184
|
+
graceful_continue { package_pips }
|
185
|
+
|
186
|
+
# Package Source
|
187
|
+
graceful_continue { package_source }
|
188
|
+
|
189
|
+
# Compress Package
|
190
|
+
graceful_continue { compress_package }
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
register_handler_for :build_lambdas
|
195
|
+
|
196
|
+
class CreateLambdas < Lambdas
|
197
|
+
def create_lambda
|
198
|
+
opt_hash = lambda_config['lambda_function'].merge 'code': {'zip_file': IO.read("#{workspace}/package.zip")}
|
199
|
+
opt_hashv = lambda_config['lambda_function'].merge('code': {'zip_file': 'IO.read("#{workspace}/package.zip"'})
|
200
|
+
opts = opt_hash.symbolize_keys
|
201
|
+
optsv = opt_hashv.symbolize_keys
|
202
|
+
title = "Deploy"
|
203
|
+
|
204
|
+
verbose_msg_for(title, optsv)
|
205
|
+
Lambit::Aws::Lambda::Function.new(opts).create_function unless Lambit.is_dry_run?
|
206
|
+
end
|
207
|
+
|
208
|
+
def process
|
209
|
+
super
|
210
|
+
graceful_continue { create_lambda }
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
register_handler_for :create_lambdas
|
215
|
+
|
216
|
+
class DeleteLambdas < Lambdas
|
217
|
+
def delete_lambda
|
218
|
+
opt_hash = lambda_config['lambda_function'].symbolize_keys
|
219
|
+
opts = opt_hash.symbolize_keys
|
220
|
+
title = "Delete"
|
221
|
+
|
222
|
+
verbose_msg_for(title, opts)
|
223
|
+
Lambit::Aws::Lambda::Function.new(opts).delete_function unless Lambit.is_dry_run?
|
224
|
+
end
|
225
|
+
|
226
|
+
def process
|
227
|
+
super
|
228
|
+
graceful_continue { delete_lambda }
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
register_handler_for :delete_lambdas
|
233
|
+
|
234
|
+
class AddEventSourcesLambdas < Lambdas
|
235
|
+
def add_lambda_permissions
|
236
|
+
lambda_config['lambda_permissions'].each_with_index do |permission, index|
|
237
|
+
@index = index
|
238
|
+
opt_hash = parse_hash(permission)
|
239
|
+
opts = opt_hash.symbolize_keys
|
240
|
+
title = "Add Lambda Permission"
|
241
|
+
|
242
|
+
verbose_msg_for(title, opts)
|
243
|
+
Lambit::Aws::Lambda::Permission.new(opts).add unless Lambit.is_dry_run?
|
244
|
+
end if lambda_config['lambda_permissions']
|
245
|
+
end
|
246
|
+
|
247
|
+
def add_s3_bucket_notification_configurations
|
248
|
+
lambda_config['s3_bucket_notification_configurations'].each_with_index do |configuration, index|
|
249
|
+
@index = index
|
250
|
+
opt_hash = parse_hash(configuration)
|
251
|
+
opts = opt_hash.symbolize_keys_deep
|
252
|
+
title = "Add S3 Bucket Configurations"
|
253
|
+
|
254
|
+
verbose_msg_for(title, opts)
|
255
|
+
Lambit::Aws::S3::BucketNotificationConfiguration.new(opts).add unless Lambit.is_dry_run?
|
256
|
+
end if lambda_config['s3_bucket_notification_configurations']
|
257
|
+
end
|
258
|
+
|
259
|
+
def put_cloudwatch_event_rules
|
260
|
+
lambda_config['cloudwatch_event_rules'].each do |rule|
|
261
|
+
opt_hash = parse_hash(rule)
|
262
|
+
opts = rule.merge(opt_hash).symbolize_keys
|
263
|
+
title = "Add CloudWatch Event Rule"
|
264
|
+
|
265
|
+
verbose_msg_for(title, opts)
|
266
|
+
Lambit::Aws::CloudWatchEvents::Rule.new(opts).put_rule unless Lambit.is_dry_run?
|
267
|
+
end if lambda_config['cloudwatch_event_rules']
|
268
|
+
end
|
269
|
+
|
270
|
+
def add_cloudwatch_event_targets
|
271
|
+
lambda_config['cloudwatch_event_targets'].each_with_index do |targets, index|
|
272
|
+
@index = index
|
273
|
+
opt_hash = parse_hash(targets)
|
274
|
+
opts = opt_hash.symbolize_keys_deep
|
275
|
+
title = "Add CloudWatch Event Targets"
|
276
|
+
|
277
|
+
verbose_msg_for(title, opts)
|
278
|
+
Lambit::Aws::CloudWatchEvents::Rule.new(opts).put_targets unless Lambit.is_dry_run?
|
279
|
+
end if lambda_config['cloudwatch_event_targets']
|
280
|
+
end
|
281
|
+
|
282
|
+
def process
|
283
|
+
super
|
284
|
+
# Add Lambda Permissions
|
285
|
+
graceful_continue { add_lambda_permissions }
|
286
|
+
|
287
|
+
# Add S3 Bucket Notification Configurations
|
288
|
+
graceful_continue { add_s3_bucket_notification_configurations }
|
289
|
+
|
290
|
+
# Put CloudWatch Event Rules
|
291
|
+
graceful_continue { put_cloudwatch_event_rules }
|
292
|
+
|
293
|
+
# Add CloudWatch Event Targets
|
294
|
+
graceful_continue { add_cloudwatch_event_targets }
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
register_handler_for :add_event_sources_lambdas
|
299
|
+
|
300
|
+
class RemoveEventSourcesLambdas < Lambdas
|
301
|
+
def remove_lambda_permissions
|
302
|
+
lambda_config['lambda_permissions'].each_with_index do |permission, index|
|
303
|
+
@index = index
|
304
|
+
opt_hash = parse_hash(permission)
|
305
|
+
opts = opt_hash.symbolize_keys
|
306
|
+
title = "Remove Lambda Permissions"
|
307
|
+
|
308
|
+
verbose_msg_for(title, opts)
|
309
|
+
Lambit::Aws::Lambda::Permission.new(opts).remove unless Lambit.is_dry_run?
|
310
|
+
end if lambda_config['lambda_permissions']
|
311
|
+
end
|
312
|
+
|
313
|
+
def remove_s3_bucket_notification_configurations
|
314
|
+
lambda_config['s3_bucket_notification_configurations'].each_with_index do |configuration, index|
|
315
|
+
@index = index
|
316
|
+
opt_hash = parse_hash(configuration)
|
317
|
+
opts = opt_hash.symbolize_keys_deep
|
318
|
+
title = "Remove S3 Bucket Configurations"
|
319
|
+
|
320
|
+
verbose_msg_for(title, opts)
|
321
|
+
Lambit::Aws::S3::BucketNotificationConfiguration.new(opts).remove unless Lambit.is_dry_run?
|
322
|
+
end if lambda_config['s3_bucket_notification_configurations']
|
323
|
+
end
|
324
|
+
|
325
|
+
def remove_cloudwatch_event_targets
|
326
|
+
lambda_config['cloudwatch_event_targets'].each_with_index do |targets, index|
|
327
|
+
@index = index
|
328
|
+
opt_hash = parse_hash(targets)
|
329
|
+
opts = opt_hash.symbolize_keys_deep
|
330
|
+
title = "Remove CloudWatch Event Targets"
|
331
|
+
|
332
|
+
verbose_msg_for(title, opts)
|
333
|
+
Lambit::Aws::CloudWatchEvents::Rule.new(opts).remove_targets unless Lambit.is_dry_run?
|
334
|
+
end if lambda_config['cloudwatch_event_targets']
|
335
|
+
end
|
336
|
+
|
337
|
+
def remove_cloudwatch_event_rules
|
338
|
+
lambda_config['cloudwatch_event_rules'].each do |rule|
|
339
|
+
@index = index
|
340
|
+
opt_hash = parse_hash(rule)
|
341
|
+
opts = opt_hash.symbolize_keys
|
342
|
+
title = "Remove CloudWatch Event Rules"
|
343
|
+
|
344
|
+
verbose_msg_for(title, opts)
|
345
|
+
Lambit::Aws::CloudWatchEvents::Rule.new(opts).delete_rule unless Lambit.is_dry_run?
|
346
|
+
end if lambda_config['cloudwatch_event_rules']
|
347
|
+
end
|
348
|
+
|
349
|
+
def process
|
350
|
+
super
|
351
|
+
# Remove Lambda Permissions
|
352
|
+
graceful_continue { remove_lambda_permissions }
|
353
|
+
|
354
|
+
# Remove S3 Bucket Notification Configurations
|
355
|
+
graceful_continue { remove_s3_bucket_notification_configurations }
|
356
|
+
|
357
|
+
# Remove CloudWatch Event Targets
|
358
|
+
graceful_continue { remove_cloudwatch_event_targets }
|
359
|
+
|
360
|
+
# Remove CloudWatch Event Rules
|
361
|
+
graceful_continue { remove_cloudwatch_event_rules }
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
register_handler_for :remove_event_sources_lambdas
|
366
|
+
|
367
|
+
class AddAlarmsLambdas < Lambdas
|
368
|
+
def add_alarms
|
369
|
+
lambda_config['cloudwatch_alarms'].each_with_index do |alarm_config, index|
|
370
|
+
@index = index
|
371
|
+
opt_hash = parse_hash(alarm_config)
|
372
|
+
opts = opt_hash.symbolize_keys_deep
|
373
|
+
title = "Remove CloudWatch Alarms"
|
374
|
+
|
375
|
+
verbose_msg_for(title, opts)
|
376
|
+
Lambit::Aws::CloudWatch::Alarm.new(opts).put_metric_alarm unless Lambit.is_dry_run?
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
def process
|
381
|
+
super
|
382
|
+
graceful_continue { add_alarms }
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
register_handler_for :add_alarms_lambdas
|
387
|
+
|
388
|
+
class DeleteAlarmsLambdas < Lambdas
|
389
|
+
def delete_alarms
|
390
|
+
alarm_names = []
|
391
|
+
|
392
|
+
lambda_config['cloudwatch_alarms'].each_with_index do |alarm_config, index|
|
393
|
+
alarm_hash = parse_hash(alarm_config)
|
394
|
+
alarm_names << alarm_hash['alarm_name']
|
395
|
+
end
|
396
|
+
|
397
|
+
opts = {:alarm_names => alarm_names}
|
398
|
+
title = "Delete CloudWatch Alarms"
|
399
|
+
verbose_msg_for(title, opts)
|
400
|
+
Lambit::Aws::CloudWatch::Alarm.new(opts).delete_alarms unless Lambit.is_dry_run?
|
401
|
+
end
|
402
|
+
|
403
|
+
def process
|
404
|
+
super
|
405
|
+
graceful_continue { delete_alarms }
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
register_handler_for :delete_alarms_lambdas
|
410
|
+
end
|
411
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
using Lambit::Common::StringHelper
|
4
|
+
|
5
|
+
module Lambit::Commands
|
6
|
+
module Subcommands
|
7
|
+
def self.run(cmd, opts, args)
|
8
|
+
handler = handler_for cmd
|
9
|
+
output, exitstatus = handler.run opts, args
|
10
|
+
|
11
|
+
# Send Subcommand output to STDOUT if :debug
|
12
|
+
if Lambit.is_debug?
|
13
|
+
puts output unless output.nil? || output.empty?
|
14
|
+
end
|
15
|
+
|
16
|
+
# Return exit status
|
17
|
+
exitstatus
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.normalize_cmd(cmd)
|
21
|
+
cmd.to_s.downcase
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.handler_for(cmd)
|
25
|
+
if @handlers
|
26
|
+
@handlers[normalize_cmd(cmd)]
|
27
|
+
else
|
28
|
+
raise 'Uh Oh!'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.register_handler_for(cmd, handler=nil)
|
33
|
+
normalized_cmd = normalize_cmd(cmd)
|
34
|
+
handler = self.const_get(normalized_cmd.classify) if handler.nil?
|
35
|
+
|
36
|
+
@handlers ||= {}
|
37
|
+
@handlers[normalized_cmd] = handler
|
38
|
+
end
|
39
|
+
|
40
|
+
class Base
|
41
|
+
attr_reader :subcommand
|
42
|
+
attr_reader :dry_run
|
43
|
+
attr_reader :exitstatus
|
44
|
+
|
45
|
+
def initialize(opts, args)
|
46
|
+
@dry_run = opts['dry-run']
|
47
|
+
@exitstatus = 1
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.run(opts, args)
|
51
|
+
output, exitstatus = self.new(opts, args).run
|
52
|
+
return output, exitstatus
|
53
|
+
end
|
54
|
+
|
55
|
+
def subcommand
|
56
|
+
@subcommand = nil
|
57
|
+
end
|
58
|
+
|
59
|
+
def output(stdout)
|
60
|
+
stdout
|
61
|
+
end
|
62
|
+
|
63
|
+
def run
|
64
|
+
raise "subcommand can't be nil" if subcommand.nil?
|
65
|
+
|
66
|
+
if dry_run
|
67
|
+
stdout = "DRY RUN: Subcommand => #{subcommand}"
|
68
|
+
@exitstatus = 0
|
69
|
+
else
|
70
|
+
# puts "Running: Subcommand => #{subcommand}"
|
71
|
+
stdout = `#{subcommand}`
|
72
|
+
@exitstatus = $?.exitstatus
|
73
|
+
end
|
74
|
+
|
75
|
+
return output(stdout), self.exitstatus
|
76
|
+
end
|
77
|
+
|
78
|
+
def successful?
|
79
|
+
self.exitstatus == 0
|
80
|
+
end
|
81
|
+
|
82
|
+
def is_successful?(status)
|
83
|
+
status == 0
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|