lambda_deployment 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3c703c23c73564ef0a8f7bd9124ad25f4c3c7abe
4
+ data.tar.gz: 72a2a8888964fa26bad41af062a81411e708bf9e
5
+ SHA512:
6
+ metadata.gz: 64b21dc6b85d9a9ac17fba736cadc6c39998b3e760425245c9155509766054ed96ad5cbdad5ddba987b784df7712fd5472c977016f75abc1f572fbf1e0a5d7b6
7
+ data.tar.gz: 555176f4ddff69b6435aa286234746eabbad8c79dfe8bef09eea60d34e980217aef964dd534118e24d52271795bb47603fabdb5058f97211448c66b2668c7f0f
data/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # lambda_deployment
2
+ Ruby gem for deploying lambda functions in AWS with Samson or another tool.
3
+ **This gem is used to update the function code only** - the resources must
4
+ already be provisioned using another tool (or manually).
5
+
6
+ [![Build Status](https://travis-ci.org/zendesk/lambda_deployment.svg?branch=master)](https://travis-ci.org/zendesk/lambda_deployment)
7
+
8
+ ## Usage
9
+ This gem provides a binary called `lambda_deploy` which will deploy a zip or
10
+ jar file to lambda, version it, and promote it to production (release).
11
+ Usage:
12
+ ```
13
+ lambda_deploy [-c path/to/configuration.yml] deploy|release
14
+ ```
15
+
16
+ ### Deploy action
17
+ The deploy action will upload the function to S3, and update the function to
18
+ use the new code. If the environmental variable `TAG` is set it will also
19
+ create a version and link that version to an alias named `TAG`.
20
+
21
+ ### Release action
22
+ The release action will link the `production` alias to the version referenced
23
+ by the `TAG` alias. **If `TAG` is not set this action is only required if the
24
+ `production` alias is not already pointing to `$LATEST`.**
25
+
26
+ ## Environmental variables
27
+ The configuration file is intentionally small with the option to override
28
+ environmental variables. The default action is to fetch values from the
29
+ environment to ensure consistency within a given environment. These variables
30
+ should be set within the deploy tool or using the configuration file.
31
+
32
+ ### AWS_REGION (required)
33
+ Region in AWS where resources are located.
34
+
35
+ ### LAMBDA_ASSUME_ROLE (optional)
36
+ STS assume role to use if resources are in another account.
37
+
38
+ ### LAMBDA_S3_BUCKET (required)
39
+ Name of S3 bucket to upload function to. Buckets can be provisioned per project
40
+ or per environment.
41
+
42
+ ### LAMBDA_S3_SSE (optional)
43
+ Type of encryption to use with S3.
44
+
45
+ ### TAG (optional)
46
+ Version of the function being uploaded (e.g. git tag).
47
+
48
+ ## Quickstart Guide
49
+ See the `examples/lambda` directory for a sample project layout.
50
+
51
+ ### Add the gem to your project
52
+ Add the following line to your `Gemfile` and run `bundle install`:
53
+ ```
54
+ gem 'lambda_deployment'
55
+ ```
56
+
57
+ ### Create a lambda_deploy.yml configuration file
58
+ The only required fields are the project name (the function name in AWS), and
59
+ the zip or jar file to upload (containing at least the script named after the
60
+ lambda_function).
61
+
62
+ Here is an example:
63
+ ```
64
+ file_name: lambda/foobar.zip # required: zip or jar of lambda function and dependencies
65
+ project: my-dev-lambda-name # required: name of lambda function
66
+ region: us-east-1 # optional: specify AWS region (will override $AWS_REGION)
67
+ s3_bucket: my-test-bucket # optional: specify s3 bucket (will override $LAMBDA_S3_BUCKET)
68
+ s3_sse: AES256 # optional: set server side encryption on s3 objects (will override $LAMBDA_S3_SSE)
69
+ ```
70
+
71
+ * *file_name* is a path relative to the configuration file
72
+ * *project* must match the function name in the AWS console (the last value in
73
+ the following example):
74
+ ```
75
+ arn:aws:lambda:<region>:<account_id>:function:<project>
76
+ ```
77
+
78
+ ### Create lambda function and s3 bucket
79
+ The lambda function and s3 buckets must already exist to use this gem. If you
80
+ are creating actions for your lambda make sure they execute the `production`
81
+ alias (see below). To do this append `:production` to the end of the ARN
82
+ associated with your lambda function.
83
+
84
+ ### Create `production` alias for lambda function
85
+ In the lambda console chose *Create alias* from the *Actions* drop down. The
86
+ name should be `production` and version should point to `$LATEST`.
data/bin/lambda_deploy ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'lambda_deployment/cli'
4
+
5
+ LambdaDeployment::CLI.new.run(ARGV)
@@ -0,0 +1,42 @@
1
+ require 'lambda_deployment'
2
+
3
+ module LambdaDeployment
4
+ class CLI
5
+ def run(args)
6
+ parse_args(args)
7
+ case @action
8
+ when 'deploy'
9
+ deploy
10
+ when 'release'
11
+ release
12
+ else
13
+ raise 'Action must be either deploy or release'
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def config
20
+ @config ||= LambdaDeployment::Configuration.new
21
+ end
22
+
23
+ def deploy
24
+ LambdaDeployment::Lambda::Deploy.new(config).run
25
+ end
26
+
27
+ def release
28
+ LambdaDeployment::Lambda::Release.new(config).run
29
+ end
30
+
31
+ def parse_args(args)
32
+ config_file = 'lambda_deploy.yml'
33
+ OptionParser.new do |opts|
34
+ opts.banner = 'Usage: lambda_deploy [-c FILE] deploy|release'
35
+ opts.version = LambdaDeployment::VERSION
36
+ opts.on('-c', '--config [FILE]', 'Use specified config file') { |c| config_file = c }
37
+ end.parse!(args)
38
+ @action = args.shift
39
+ config.load_config(config_file)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,32 @@
1
+ module LambdaDeployment
2
+ class Client
3
+ def initialize(region)
4
+ @region = region
5
+ end
6
+
7
+ def lambda_client
8
+ @lambda_client ||= Aws::Lambda::Client.new(config)
9
+ end
10
+
11
+ def s3_client
12
+ @s3_client ||= Aws::S3::Client.new(config)
13
+ end
14
+
15
+ private
16
+
17
+ def config
18
+ config = { region: @region }
19
+ if role_arn
20
+ config[:credentials] = Aws::AssumeRoleCredentials.new(
21
+ role_arn: role_arn,
22
+ role_session_name: SecureRandom.hex(10)
23
+ )
24
+ end
25
+ config
26
+ end
27
+
28
+ def role_arn
29
+ ENV.fetch('LAMBDA_ASSUME_ROLE', false)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,29 @@
1
+ module LambdaDeployment
2
+ class Configuration
3
+ attr_reader :file_path, :project, :region, :s3_bucket, :s3_key, :s3_sse
4
+
5
+ def load_config(config_file)
6
+ config = YAML.load_file(config_file)
7
+ @project = config.fetch('project')
8
+ @region = config.fetch('region', ENV.fetch('AWS_REGION', nil))
9
+ @file_path = File.expand_path(config.fetch('file_name'), File.dirname(config_file))
10
+ raise "File not found: #{@file_path}" unless File.exist?(@file_path)
11
+
12
+ @s3_bucket = config.fetch('s3_bucket', ENV.fetch('LAMBDA_S3_BUCKET', nil))
13
+ @s3_key = s3_key_name(config.fetch('file_name'))
14
+ @s3_sse = config.fetch('s3_sse', ENV.fetch('LAMBDA_S3_SSE', nil))
15
+ end
16
+
17
+ def alias_name
18
+ ENV.fetch('TAG', nil)
19
+ end
20
+
21
+ private
22
+
23
+ def s3_key_name(file_name)
24
+ basename = File.basename(file_name, '.*')
25
+ extension = File.extname(file_name)
26
+ "#{basename}-#{ENV.fetch('TAG', 'latest')}#{extension}"
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,63 @@
1
+ module LambdaDeployment
2
+ module Lambda
3
+ class Deploy
4
+ def initialize(config)
5
+ @config = config
6
+ @client = LambdaDeployment::Client.new(config.region)
7
+ end
8
+
9
+ def run
10
+ upload_to_s3
11
+ update_function_code
12
+ return unless @config.alias_name
13
+ version = publish_version
14
+ begin
15
+ create_alias(version)
16
+ rescue Aws::Lambda::Errors::ResourceConflictException
17
+ update_alias(version)
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def upload_to_s3
24
+ @client.s3_client.put_object(
25
+ body: File.read(@config.file_path),
26
+ bucket: @config.s3_bucket,
27
+ key: @config.s3_key,
28
+ server_side_encryption: @config.s3_sse
29
+ )
30
+ end
31
+
32
+ def update_function_code
33
+ @client.lambda_client.update_function_code(
34
+ function_name: @config.project,
35
+ s3_bucket: @config.s3_bucket,
36
+ s3_key: @config.s3_key
37
+ )
38
+ end
39
+
40
+ def publish_version
41
+ @client.lambda_client.publish_version(
42
+ function_name: @config.project
43
+ ).version
44
+ end
45
+
46
+ def create_alias(version)
47
+ @client.lambda_client.create_alias(alias_params(version))
48
+ end
49
+
50
+ def update_alias(version)
51
+ @client.lambda_client.update_alias(alias_params(version))
52
+ end
53
+
54
+ def alias_params(version)
55
+ {
56
+ function_name: @config.project,
57
+ name: @config.alias_name,
58
+ function_version: version
59
+ }
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,36 @@
1
+ module LambdaDeployment
2
+ module Lambda
3
+ class Release
4
+ def initialize(config)
5
+ @config = config
6
+ @client = LambdaDeployment::Client.new(config.region)
7
+ end
8
+
9
+ def run
10
+ version = version_for_tag
11
+ update_production_alias(version)
12
+ end
13
+
14
+ private
15
+
16
+ def version_for_tag
17
+ if @config.alias_name
18
+ @client.lambda_client.get_alias(
19
+ function_name: @config.project,
20
+ name: @config.alias_name
21
+ ).function_version
22
+ else
23
+ '$LATEST'
24
+ end
25
+ end
26
+
27
+ def update_production_alias(version)
28
+ @client.lambda_client.update_alias(
29
+ function_name: @config.project,
30
+ function_version: version,
31
+ name: 'production'
32
+ )
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ module LambdaDeployment
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,10 @@
1
+ require 'aws-sdk-core'
2
+ require 'optparse'
3
+ require 'securerandom'
4
+ require 'yaml'
5
+ require 'lambda_deployment/cli'
6
+ require 'lambda_deployment/client'
7
+ require 'lambda_deployment/configuration'
8
+ require 'lambda_deployment/lambda/deploy'
9
+ require 'lambda_deployment/lambda/release'
10
+ require 'lambda_deployment/version'
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lambda_deployment
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Zendesk CloudOps
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-08-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: aws-sdk-core
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
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: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: single_cov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description:
70
+ email:
71
+ executables:
72
+ - lambda_deploy
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - README.md
77
+ - bin/lambda_deploy
78
+ - lib/lambda_deployment.rb
79
+ - lib/lambda_deployment/cli.rb
80
+ - lib/lambda_deployment/client.rb
81
+ - lib/lambda_deployment/configuration.rb
82
+ - lib/lambda_deployment/lambda/deploy.rb
83
+ - lib/lambda_deployment/lambda/release.rb
84
+ - lib/lambda_deployment/version.rb
85
+ homepage: https://github.com/zendesk/lambda_deployment
86
+ licenses: []
87
+ metadata: {}
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 2.6.8
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: Lambda Deployment Library
108
+ test_files: []