lambda_deployment 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +86 -0
- data/bin/lambda_deploy +5 -0
- data/lib/lambda_deployment/cli.rb +42 -0
- data/lib/lambda_deployment/client.rb +32 -0
- data/lib/lambda_deployment/configuration.rb +29 -0
- data/lib/lambda_deployment/lambda/deploy.rb +63 -0
- data/lib/lambda_deployment/lambda/release.rb +36 -0
- data/lib/lambda_deployment/version.rb +3 -0
- data/lib/lambda_deployment.rb +10 -0
- metadata +108 -0
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,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,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: []
|