lambda-version-manager 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []