lambda-version-manager 0.0.3

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 65c1fc87ac3d5d62b4cbc7fdcd68100c73110ebd
4
+ data.tar.gz: d6e4ac2ad9dbb56c3d23f1fd2886aeafd103f8fd
5
+ SHA512:
6
+ metadata.gz: 5f7da2339574a59efb3c099145130db05fab72691120211f93c210a6f1f39123c8d3172458393347933c2131c8f46888a0a68ac2b614bc2af47ddfa21f2ee920
7
+ data.tar.gz: b8e3b5d321133d329f9a05b8c4ee65ac9fc70705808e5b455e43621021dfa5ee184bbc1b73c0ee4a3d1c82983ed052aa53a95f0d5c082555fa8d11ec0d015115
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ require 'thor'
4
+ require 'yaml'
5
+ require 'pp'
6
+ require_relative '../lib/project'
7
+ require_relative '../lib/deployer'
8
+ class GeneratorCLI < ::Thor
9
+
10
+ desc 'deploy', 'Deploy the updated lambda versions'
11
+ option 'project_path', banner: 'PROJECT_PATH', type: :string, desc: 'Path to the lambda version mappings project'
12
+ option 'environments', banner: 'ENVIRONMENT', type: :array, desc: 'Deploy lambdas in this environment'
13
+ option 'artifact', banner: 'ARTIFACT', type: :string, desc: 'Deploy lambdas that use this artifact'
14
+ option 'lambda', banner: 'LAMBDA', type: :string, desc: 'Deploy lambdas with this name'
15
+ option 'account', banner: 'ACCOUNT', type: :string, desc: 'Account to deploy to', :required => true
16
+ option 'version_map_file', banner: 'VERSION_MAP_FILE', type: :string, desc: 'A java properties file mapping artifacts to update to version'
17
+
18
+ def deploy
19
+ opts = parse_options(options)
20
+ if opts['version_map_file']
21
+ #for each x=y pair we need to call
22
+ File.readlines(options['version_map_file']).each do |line|
23
+ array = line.split("=")
24
+ deployer = Deployer.new(opts['project_path'], opts['account'], array[0].strip)
25
+ deployer.deploy(opts['environments'])
26
+ end
27
+ else
28
+ deployer = Deployer.new(opts['project_path'], opts['account'], opts['artifact'], opts['lambda'])
29
+ deployer.deploy(opts['environments'])
30
+ end
31
+ end
32
+
33
+ desc 'update_project', 'Update the versions'
34
+ option 'project_path', banner: 'PROJECT_PATH', type: :string, desc: 'Path to the lambda version mappings project'
35
+ option 'artifact', banner: 'ARTIFACT', type: :string, desc: 'Deploy lambdas that use this artifact'
36
+ option 'version', banner: 'VERSION', type: :string, desc: 'Version of the new artifact'
37
+ option 'version_map_file', banner: 'VERSION_MAP_FILE', type: :string, desc: 'A java properties file mapping artifacts to update to version'
38
+ option 'accounts', banner: 'ACCOUNT', type: :array, desc: 'Account to deploy to', :required => true
39
+
40
+ def update_project
41
+ opts = parse_options(options)
42
+ project = Project.new(opts['project_path'])
43
+ lambda_env_map = project.get_lambdas
44
+ account_env_map = project.account_env_map
45
+
46
+ supportd_envs = []
47
+ opts['accounts'].each do | account|
48
+ supportd_envs += account_env_map[account]
49
+ end
50
+
51
+ lambda_env_map.each do |env, lamdas|
52
+ unless supportd_envs.include?(env)
53
+ lambda_env_map.delete(env)
54
+ end
55
+ end
56
+
57
+
58
+ if opts['version_map_file']
59
+ #for each artifact=version pair we need to call
60
+ File.readlines(opts['version_map_file']).each do |line|
61
+ array = line.split("=")
62
+ updated_files = project.update_by_artifact(lambda_env_map, array[0].strip, array[1].strip)
63
+ lambda_env_map = updated_files
64
+ end
65
+ else
66
+ lambda_env_map = project.update_by_artifact(lambda_env_map, opts['artifact'], opts['version'])
67
+ end
68
+ project.write_new_files(lambda_env_map)
69
+ end
70
+
71
+ no_commands do
72
+ def parse_options(options)
73
+ unless options['version_map_file'] || (options['version'] && (options['lambda'] || options['artifact']))
74
+ raise 'Either a file must be specified or a version and lambda or artifact.'
75
+ end
76
+ #add input validation, either a file must be specified or a version and lambda or artifact.
77
+ opts = options.dup
78
+ opts
79
+ end
80
+ end
81
+ end
82
+
83
+ GeneratorCLI.start(ARGV)
@@ -0,0 +1,12 @@
1
+ require 'aws-sdk-lambda'
2
+ class Client
3
+ attr_accessor :client
4
+ def initialize(aws_region)
5
+ @client = Aws::Lambda::Client.new(region: aws_region)
6
+ end
7
+
8
+ def update_function_code(function_name, s3_bucket, s3_key)
9
+ response = client.update_function_code({function_name: function_name, s3_bucket: s3_bucket, s3_key: s3_key})
10
+ puts "Updated: #{response.function_name}"
11
+ end
12
+ end
@@ -0,0 +1,86 @@
1
+ require_relative 'client'
2
+ require_relative 'project'
3
+ class Deployer
4
+ attr_accessor :project_path
5
+ attr_accessor :account
6
+ attr_accessor :config
7
+ attr_accessor :project
8
+ attr_accessor :lambda
9
+ attr_accessor :artifact
10
+
11
+ def initialize(project_path, account, artifact, lambda)
12
+ @project_path = project_path
13
+ @account = account
14
+ @project = Project.new("#{project_path}")
15
+ @config = set_config
16
+ @artifact = artifact
17
+ @lambda = lambda
18
+ end
19
+
20
+ def set_config
21
+ @project.config
22
+ end
23
+
24
+ def get_deployable_lambdas(lambda_env_map)
25
+
26
+ if artifact
27
+ lambda_env_map.each do |env, lambdas|
28
+ lambdas.each do |lambda_name, properties|
29
+ lambdas.delete(lambda_name) unless properties['artifact_name'] == artifact
30
+ end
31
+ end
32
+ end
33
+
34
+ if lambda
35
+ lambda_env_map.each do |env, lambdas|
36
+ lambdas.each do |lambda_name, properties|
37
+ lambdas.delete(lambda_name) unless lambda_name == lambda
38
+ end
39
+ end
40
+ end
41
+ lambda_env_map
42
+ end
43
+
44
+ def deploy(environments)
45
+ account_env_map = project.account_env_map[account]
46
+ env_region_map = project.env_region_map
47
+ #Filter by account as the primary owner of envs
48
+ lambda_env_map = project.get_lambdas
49
+ lambda_env_map = get_deployable_lambdas(lambda_env_map)
50
+ account_env_map.each do |env|
51
+ #IF users has specified environments, skip if the environment is not a user specified one
52
+ next if !environments.nil? && environments.include?(env)
53
+ lambda_env_map[env].each do |lambda_name, properties|
54
+ client = Client.new(env_region_map[env])
55
+
56
+ s3_bucket = get_s3_bucket(properties, env)
57
+ s3_key = construct_s3_key(properties, env)
58
+
59
+ puts "ENV: #{env}"
60
+ puts "Lambda Name: #{lambda_name}"
61
+ puts "S3 Bucket: #{s3_bucket}"
62
+ puts "S3 Key: #{s3_key}"
63
+ #client.update_function_code(lambda_name,s3_bucket,s3_key)
64
+ end
65
+ end
66
+ end
67
+
68
+
69
+ def get_s3_bucket(properties, env)
70
+ if properties['s3_bucket']
71
+ return properties['s3_bucket']
72
+ else
73
+ return config['environments'][env]['s3_bucket']
74
+ end
75
+
76
+ end
77
+
78
+ def construct_s3_key(properties, env)
79
+ if properties['s3_key']
80
+ return properties['s3_key']
81
+ else
82
+ return "#{config['environments'][env]['base_path']}/#{properties['artifact_name']}#{properties['artifact_name']}-#{properties['version']}.#{properties['extension']}"
83
+ end
84
+ end
85
+ end
86
+
@@ -0,0 +1,67 @@
1
+ class Project
2
+ attr_accessor :config
3
+ attr_accessor :project_path
4
+
5
+ def initialize(project_path)
6
+ @config = YAML.load_file("#{project_path}/config/config.yaml")
7
+ @project_path = project_path
8
+ end
9
+
10
+ def environments
11
+ config['environments']
12
+ end
13
+
14
+ def get_lambdas
15
+ lambdas = {}
16
+ environments.keys.each do |env|
17
+ lambdas[env] = YAML.load_file("#{project_path}/environments/#{env}.yaml")
18
+ end
19
+ lambdas
20
+ end
21
+
22
+ def account_env_map
23
+ hash = {}
24
+ config['environments'].each do |env, properties|
25
+ if hash[properties['account']].nil?
26
+ hash[properties['account']] = []
27
+ hash[properties['account']] << env
28
+ else
29
+ hash[properties['account']] << env
30
+ end
31
+ end
32
+ hash
33
+ end
34
+
35
+ def env_region_map
36
+ hash = {}
37
+ config['environments'].each do |env, properties|
38
+ if hash[env].nil?
39
+ hash[env] = properties['region']
40
+ else
41
+ raise("An environment cannot map to more than one region ENV: #{env} Region: #{properties['region']}")
42
+ end
43
+ end
44
+ hash
45
+ end
46
+
47
+
48
+ def write_new_files(lambda_env_map)
49
+ lambda_env_map.each do |env, contents|
50
+ File.write("#{project_path}/environments/#{env}.yaml", contents.to_yaml)
51
+ end
52
+ end
53
+
54
+ def update_by_artifact(lambda_env_map, artifact, version)
55
+ #iterate through all lambdas and update the ones with version changes
56
+ lambda_env_map.each do |env, lambda|
57
+ pp env
58
+ pp lambda
59
+ lambda.each do |lambda_name, properties|
60
+ if properties['artifact_name'] == artifact
61
+ properties['version'] = version
62
+ end
63
+ end
64
+ end
65
+ lambda_env_map
66
+ end
67
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lambda-version-manager
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Bryan Call
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-02-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: aws-sdk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.0.0.rc2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.0.0.rc2
27
+ - !ruby/object:Gem::Dependency
28
+ name: thor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thor-scmversion
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Updates aws lambda versions to match a yaml property file
56
+ email: bcall@rapid7.com
57
+ executables:
58
+ - lambda-version-manager
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - bin/lambda-version-manager
63
+ - lib/client.rb
64
+ - lib/deployer.rb
65
+ - lib/project.rb
66
+ homepage: http://rubygems.org/gems/lambda-version-manager
67
+ licenses:
68
+ - MIT
69
+ metadata: {}
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubyforge_project:
86
+ rubygems_version: 2.6.12
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: Lambda version manager
90
+ test_files: []