ruby_lambda 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3d14b2ea8a2f48a998ee212328e73e8a74a2f4512cce87e1297abd074d33d71f
4
- data.tar.gz: 5a158755424e2b161fc90ff60369c3ac6922d304655ec8e34dc3753ed8dd68c0
3
+ metadata.gz: 7a60b683ef881c5be530f4cfffdda9281d60ada742df58f0fc84b618fb1eabef
4
+ data.tar.gz: 9c380e30496609a052fb97bea89976c343a73ba24d2eff3d818a5eab48885d77
5
5
  SHA512:
6
- metadata.gz: 5c4ccbe29359ea91eaed3b7950cef7d83eff68fe0b7fa49a55e743e164b17eda481ca7b530c660ec5359c481dda7a6d6dd41ae02fa4f666dd1f78e0f428b1679
7
- data.tar.gz: 03dce8db39c13a16fa93f7c3ac5f768a2d97c96e719fd870b06218d228b845d7b807f1412eecdd7632f90e6ac9bc7184220339da8718ba5cd6c1e4588878b9fc
6
+ metadata.gz: 0bb08729f54017cf404823c43162e1a085da45e74bf11193585f4523c6bee59f06d903d245b562af24c2b863efabe8383292df40ad0b76015fe07d7bc8bc5a44
7
+ data.tar.gz: 273dbcb92c598b90a8730165f8d70ba4c9d3ffa33f3c4c0c8d7a1524e3930578276395be0aac42a3abe24e250f0097096ee71f47a71cdb3c911b17c2e1934666
data/.travis.yml CHANGED
@@ -3,5 +3,5 @@ sudo: false
3
3
  language: ruby
4
4
  cache: bundler
5
5
  rvm:
6
- - 2.5.0
6
+ - 2.5.3
7
7
  before_install: gem install bundler -v 1.16.6
data/Gemfile.lock CHANGED
@@ -1,8 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ruby_lambda (0.4.0)
4
+ ruby_lambda (0.5.0)
5
5
  awesome_print (~> 1.8.0)
6
+ aws-sdk-iam (~> 1)
7
+ aws-sdk-lambda (~> 1)
8
+ dotenv (~> 2.7)
6
9
  rubyzip (~> 1.2)
7
10
  thor (~> 0.19)
8
11
 
@@ -10,9 +13,25 @@ GEM
10
13
  remote: https://rubygems.org/
11
14
  specs:
12
15
  awesome_print (1.8.0)
16
+ aws-eventstream (1.0.3)
17
+ aws-partitions (1.163.0)
18
+ aws-sdk-core (3.52.1)
19
+ aws-eventstream (~> 1.0, >= 1.0.2)
20
+ aws-partitions (~> 1.0)
21
+ aws-sigv4 (~> 1.1)
22
+ jmespath (~> 1.0)
23
+ aws-sdk-iam (1.22.0)
24
+ aws-sdk-core (~> 3, >= 3.52.1)
25
+ aws-sigv4 (~> 1.1)
26
+ aws-sdk-lambda (1.25.0)
27
+ aws-sdk-core (~> 3, >= 3.52.1)
28
+ aws-sigv4 (~> 1.1)
29
+ aws-sigv4 (1.1.0)
30
+ aws-eventstream (~> 1.0, >= 1.0.2)
13
31
  coderay (1.1.2)
14
32
  diff-lcs (1.3)
15
33
  docile (1.3.1)
34
+ dotenv (2.7.2)
16
35
  ffi (1.9.25)
17
36
  formatador (0.2.5)
18
37
  guard (2.15.0)
@@ -29,6 +48,7 @@ GEM
29
48
  guard (~> 2.1)
30
49
  guard-compat (~> 1.1)
31
50
  rspec (>= 2.99.0, < 4.0)
51
+ jmespath (1.4.0)
32
52
  json (2.1.0)
33
53
  listen (3.1.5)
34
54
  rb-fsevent (~> 0.9, >= 0.9.4)
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # RubyLambda
1
+ # RubyLambda [![Build Status](https://travis-ci.org/cookieshq/ruby_lambda.svg?branch=develop)](https://travis-ci.org/cookieshq/ruby_lambda)
2
2
 
3
3
  RubyLambda is a toolset for developing and deploying serverless Ruby apps in AWS Lambda.
4
4
 
@@ -20,19 +20,19 @@ $ ruby-lambda deploy
20
20
 
21
21
  ### Commands
22
22
 
23
- #### ruby-lambda init
23
+ ### ruby-lambda init
24
24
  ```
25
25
  $ ruby-lambda init
26
26
  ```
27
27
 
28
28
  Initializes the `.gitignore`, `config.yml`, `env`, `event.json`, `lambda_function.rb`, `Gemfile`, `.ruby-version` files.
29
- * `event.json` is where you keep mock data that will be passed to your function when the `execute` command has ran.
29
+ * `event.json` is where you keep mock data that will be passed to your function when the `execute` command runs.
30
30
  * `config.yml` contains some default configuration for your function.
31
31
  * `env` will be renamed to `.env` after the init command runs, it will contain `AWS_ACCESS_KEY` and `AWS_SECRET_ACCESS_KEY`. You will need these to be able to deploy your function.
32
32
 
33
33
  Please have a read of the `config.yml` and update any of the default configuration to better suit your function to AWS.
34
34
 
35
- #### ruby-lambda execute
35
+ ### ruby-lambda execute
36
36
  ```
37
37
  $ ruby-lambda execute
38
38
  ```
@@ -40,8 +40,8 @@ This command is used to invoke / run the function locally
40
40
 
41
41
  ```
42
42
  Options:
43
- -c, [--config=CONFIG] # Default: config.yml
44
- -H, [--handler=HANDLER]
43
+ -c, --config=CONFIG # Default: config.yml
44
+ -H, --handler=HANDLER
45
45
  ```
46
46
 
47
47
  **Examples**
@@ -58,7 +58,7 @@ end
58
58
 
59
59
  The `execute` command gets the values stored in the `event.json` file and passes them to your handler function.
60
60
 
61
- #### ruby-lambda build
61
+ ### ruby-lambda build
62
62
  ```
63
63
  $ ruby-lambda build
64
64
  ```
@@ -66,17 +66,52 @@ This command will create a zipped file ready to be published on Lambda
66
66
 
67
67
  ```
68
68
  Options:
69
- -n, [--native-extensions], [--no-native-extensions]
70
- -q, [--quiet], [--no-quiet]
69
+ -n, --native-extensions
70
+ -q, --quiet
71
71
  ```
72
72
 
73
73
  All output zipped will in the builds folder within the project root - the build folder will be created if one does not already exists.
74
74
 
75
+ **Native Extensions**
76
+
77
+ This [article](http://patshaughnessy.net/2011/10/31/dont-be-terrified-of-building-native-extensions) covers what native extensions are and a lot more information about how they work. Basically, building native extensions are nothing but compiling C code into the platform and environment specific machine language code. So, if you run bundle install — deployment on your local machine running MacOS, the C code is compiled for MacOS and stored in vendor/bundle. As AWS lambda is a Ubuntu machine, not MacOs it won’t work.
78
+
79
+ To build gems with Native extensions use `-n` flag when you run this command. Doing so will run a dockerized bundle with deployment flag within a Lambda image – this will download the gems to the local directory instead of to the local systems Ruby directory, using the same OS environment as Lambda so that it installs the correct native extensions. This ensures that all our dependencies are included in the function deployment package and the correct native extensions will be called.
80
+
81
+
82
+ ### ruby-lambda deploy
83
+ ```
84
+ $ ruby-lambda deploy
85
+
86
+ ```
87
+ The deploy command will either bundle install your project and package it in a zip or accept a zip file passed to it then uploads it to AWS Lambda.
88
+
89
+ ```
90
+ Options:
91
+ -n, --native-extensions flag to pass build gems with native extensions
92
+ -c, --config=CONFIG path to the config file, defalt is config.yml
93
+ -p, --publish if the function should be published, default is true
94
+ -u, --update default to true, update the function
95
+ -z, --zip-file=ZIP_FILE path to zip file to create or update your function
96
+ -q, --quiet
97
+ ```
98
+
99
+ By default the `deploy` command will attepmt to create the function with your config, if the function already exists an error will be thrown. To update an existing function simply pass the `-u` flag.
100
+
101
+
102
+ When you publish a version, AWS Lambda makes a snapshot copy of the Lambda function code (and configuration) in the $LATEST version. A published version is immutable. That is, you can't change the code or configuration information. The new version has a unique ARN that includes a version number suffix. AWS recommends that you publish a version at the same time that you create your Lambda function or update your Lambda function code. So by default all deploy will be versioned, if you do not want this, use `-p=false` flag.
103
+
104
+ When you run the deploy command we will prepare the latest state of your function and zip it up, basically running the build command. If you have already built your zip, use the `-z` flag to set the path to it.
75
105
 
76
106
  ## Roadmap
77
- Below is the roadmap to version 1
78
107
 
79
- - [ ] Add a way to deploy directly to AWS lambda
108
+ - [ ] Add an option to add APIGate way to allow functions to have an end point
109
+ - [ ] Add the ability to deploy different ruby versions using layers
110
+ - [ ] Add an options to choose zip uploaded to s3
111
+ - [ ] Add option to allow deploy to use value passed through the flags
112
+ - [ ] Add more deploy options
113
+ - [ ] Add environment variables to be passed in deploying
114
+ - [x] Add a way to deploy and update Lambda functions
80
115
  - [x] Add ablility to execute the function offline
81
116
  - [x] Add json file or options to be passed to execute function
82
117
  - [x] Add a way to build files in to zips ready to be deployed to lambda
@@ -87,7 +122,7 @@ Below is the roadmap to version 1
87
122
 
88
123
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
89
124
 
90
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
125
+ To install this gem onto your local machine, run `bundle exec rake install`.
91
126
 
92
127
  ## Contributing
93
128
 
@@ -100,4 +135,3 @@ The gem is available as open source under the terms of the [MIT License](https:/
100
135
  ## Code of Conduct
101
136
 
102
137
  Everyone interacting in the RubyLambda project’s codebases and issue trackers is expected to follow the [code of conduct](https://github.com/cookieshq/ruby_lambda/blob/master/CODE_OF_CONDUCT.md).
103
-
data/bin/ruby-lambda CHANGED
@@ -47,6 +47,27 @@ class RubyLambdaCLI < Thor
47
47
  def build
48
48
  RubyLambda::Build.new(FileUtils.pwd, options).run(mute: options[:quiet])
49
49
  end
50
+
51
+ desc 'publish', 'Builds your function into a local ready to deploy zip file'
52
+ long_desc <<-LONGDESC
53
+ The deploy command will either bundle install your project and package it in a zip or accept a zip file passed to it then uploads it to AWS Lambda.
54
+
55
+ With -n, --native-extensions flag to pass build gems with native extensions
56
+ -c, --config=CONFIG path to the config file, defalt is config.yml
57
+ -p, --publish if the function should be published, default is true
58
+ -u, --update default to true, update the function
59
+ -z, --zip-file=ZIP_FILE path to zip file to create or update your function
60
+ -q, --quiet
61
+ LONGDESC
62
+
63
+ option :native_extensions, type: :boolean, default: false, aliases: :n
64
+ option :publish, type: :boolean, default: true, aliases: :p
65
+ option :update, type: :boolean, default: false, aliases: :u
66
+ option :config, default: 'config.yml', type: :string, aliases: :c
67
+ option :zip_file, type: :string, aliases: :z
68
+ def deploy
69
+ RubyLambda::Deploy.new(FileUtils.pwd, options).run(mute: options[:quiet])
70
+ end
50
71
  end
51
72
 
52
73
  RubyLambdaCLI.start(ARGV)
@@ -1,6 +1,6 @@
1
1
  module RubyLambda
2
2
  class Build
3
- def initialize(current_directory, options = {"native_extensions"=>false})
3
+ def initialize(current_directory, options = {"native_extensions"=>false, 'file_name' => ''})
4
4
  @current_directory = current_directory
5
5
  @shell = Thor::Base.shell.new
6
6
  @options = options
@@ -9,7 +9,7 @@ module RubyLambda
9
9
  def run(mute: false)
10
10
  @mute = mute
11
11
 
12
- if @options[:native_extensions]
12
+ if @options['native_extensions']
13
13
  unless which('docker')
14
14
  @shell.say 'Can not find docker, you need to install docker if you want to build with native extensions', :red
15
15
  return
@@ -56,6 +56,8 @@ module RubyLambda
56
56
 
57
57
  new_file_name = ''
58
58
 
59
+ return @options['file_name'] if @options['file_name'] && @options['file_name'] != ''
60
+
59
61
  begin
60
62
  new_build_number = new_build_number + 1
61
63
 
@@ -0,0 +1,154 @@
1
+ module RubyLambda
2
+ class Deploy
3
+ def initialize(current_directory, options = {'native_extensions' => false, 'config' => 'config.yml'})
4
+ @current_directory = current_directory
5
+ @shell = Thor::Base.shell.new
6
+ @options = options
7
+ end
8
+
9
+ def run(mute: false)
10
+ @mute = mute
11
+
12
+ @config_data = load_data_from_config_file
13
+
14
+ Aws.config.update({
15
+ credentials: Aws::Credentials.new(@config_data['aws_access_key'], @config_data['aws_secret_access_key'])
16
+ })
17
+
18
+ @iam_client = Aws::IAM::Client.new(region: @config_data['region'])
19
+
20
+ @iam = Aws::IAM::Resource.new(client: @iam_client)
21
+
22
+ @client = Aws::Lambda::Client.new(region: @config_data['region'])
23
+
24
+ deploy_options = {}
25
+
26
+ deploy_options[:role] = get_role_arn
27
+ deploy_options[:function_name] = @config_data['function_name']
28
+ deploy_options[:handler] = @config_data['handler']
29
+ deploy_options[:runtime] = @config_data['runtime']
30
+ deploy_options[:publish] = @options['publish']
31
+
32
+ if @options['zip_file']
33
+ zip_file = @options['zip_file']
34
+ else
35
+ zip_file = get_temp_build_zip
36
+ end
37
+
38
+ deploy_options[:code] = { zip_file: File.open(zip_file, 'rb').read }
39
+
40
+ function = deploy_function(deploy_options)
41
+
42
+ clean_up
43
+
44
+ ap function
45
+ @shell.say('Function deployed', :green) unless @mute
46
+ end
47
+
48
+ def load_data_from_config_file
49
+ begin
50
+ config_data = YAML.load(ERB.new(File.read("#{@current_directory}/#{@options['config']}")).result)
51
+
52
+ raise RubyLambda::ExecuteError.new('Invalid config file') unless config_data.is_a?(Hash)
53
+
54
+ config_data
55
+ rescue Errno::ENOENT
56
+ no_config_file_message = 'Config file missing, create a config.yml file or use the -c / --config flag to pass a different config file.'
57
+
58
+ @shell.say(no_config_file_message, :red)
59
+
60
+ exit 1
61
+ rescue RubyLambda::ExecuteError
62
+ @shell.say('Invalid config file', :red)
63
+
64
+ exit 1
65
+ end
66
+ end
67
+
68
+ def get_temp_build_zip
69
+ @zip_file_name = "#{Time.now.strftime('%Y-%m-%d_%H-%M-%S')}_deploy_build.zip"
70
+
71
+ RubyLambda::Build.new(@current_directory, {'file_name' => @zip_file_name, 'native_extensions' => @options['native_extensions']}).run(mute: @mute)
72
+
73
+ @zip_file_name
74
+ end
75
+
76
+ def clean_up
77
+ return if @options['zip_file'] != ''
78
+
79
+ FileUtils.rm "#{@current_directory}/#{@zip_file_name}"
80
+ end
81
+
82
+ def deploy_function(deploy_options)
83
+ begin
84
+ if @options['update']
85
+ update_function(deploy_options)
86
+ else
87
+ @client.create_function(deploy_options)
88
+ end
89
+ rescue Aws::Lambda::Errors::ResourceConflictException
90
+ if @options['update']
91
+ update_function(deploy_options)
92
+ else
93
+ @shell.say('Function already exists use the --update flag to update the current function', :red)
94
+ clean_up
95
+ exit 1
96
+ end
97
+ end
98
+ end
99
+
100
+ def update_function(deploy_options)
101
+ begin
102
+ update_options = {}
103
+ update_options[:function_name] = deploy_options[:function_name]
104
+ update_options[:publish] = deploy_options[:publish]
105
+ update_options[:zip_file] = deploy_options[:code][:zip_file]
106
+
107
+ @client.update_function_code(update_options)
108
+ rescue Aws::Lambda::Errors::ResourceNotFoundException
109
+ @shell.say('Function was not found, remove the --update flag to create it', :red)
110
+ clean_up
111
+ exit 1
112
+ end
113
+ end
114
+
115
+ def get_role_arn
116
+ begin
117
+ new_role = @iam_client.get_role({
118
+ role_name: 'ruby_lambda_gem_basic_execution_role',
119
+ })
120
+
121
+ new_role.role.arn
122
+ rescue Aws::IAM::Errors::NoSuchEntity
123
+ create_role.data.arn
124
+ end
125
+ end
126
+
127
+ def create_role
128
+ policy_doc = {
129
+ Version:'2012-10-17',
130
+ Statement:[
131
+ {
132
+ Effect:'Allow',
133
+ Action:'sts:AssumeRole',
134
+ Principal:{
135
+ Service:'lambda.amazonaws.com'
136
+ }
137
+ }]
138
+ }
139
+
140
+ role = @iam.create_role({
141
+ role_name: 'ruby_lambda_gem_basic_execution_role',
142
+ description: 'Role created to deploy lambda functions from ruby lambda gem',
143
+ assume_role_policy_document: policy_doc.to_json
144
+ })
145
+
146
+ role.attach_policy({
147
+ policy_arn: 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
148
+ })
149
+
150
+ sleep 5 # This will give the policy enough time to be attached to the role https://stackoverflow.com/a/37438525/7157278
151
+ role
152
+ end
153
+ end
154
+ end
@@ -1,3 +1,3 @@
1
1
  module RubyLambda
2
- VERSION = '0.4.0'
2
+ VERSION = '0.5.0'
3
3
  end
data/lib/ruby_lambda.rb CHANGED
@@ -1,15 +1,21 @@
1
1
  require 'json'
2
2
  require 'thor'
3
3
  require 'fileutils'
4
- require 'awesome_print'
5
4
  require 'yaml'
5
+ require 'erb'
6
+ require 'tempfile'
6
7
  require 'zip'
8
+ require 'awesome_print'
9
+ require 'dotenv/load'
10
+ require 'aws-sdk-lambda'
11
+ require 'aws-sdk-iam'
7
12
 
8
13
  require 'ruby_lambda/version'
9
14
  require 'ruby_lambda/error'
10
15
  require 'ruby_lambda/init'
11
16
  require 'ruby_lambda/execute'
12
17
  require 'ruby_lambda/build'
18
+ require 'ruby_lambda/deploy'
13
19
 
14
20
  module RubyLambda
15
21
  end
data/ruby_lambda.gemspec CHANGED
@@ -31,6 +31,9 @@ Gem::Specification.new do |spec|
31
31
  spec.add_runtime_dependency 'thor', '~> 0.19'
32
32
  spec.add_runtime_dependency 'awesome_print', '~> 1.8.0'
33
33
  spec.add_runtime_dependency 'rubyzip', '~> 1.2'
34
+ spec.add_runtime_dependency 'dotenv', '~> 2.7'
35
+ spec.add_runtime_dependency 'aws-sdk-lambda', '~> 1'
36
+ spec.add_runtime_dependency 'aws-sdk-iam', '~> 1'
34
37
 
35
38
  spec.add_development_dependency 'bundler', '~> 1.16'
36
39
  spec.add_development_dependency 'rake', '~> 10.0'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_lambda
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - cookieshq
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-05-14 00:00:00.000000000 Z
12
+ date: 2019-05-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
@@ -53,6 +53,48 @@ dependencies:
53
53
  - - "~>"
54
54
  - !ruby/object:Gem::Version
55
55
  version: '1.2'
56
+ - !ruby/object:Gem::Dependency
57
+ name: dotenv
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '2.7'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '2.7'
70
+ - !ruby/object:Gem::Dependency
71
+ name: aws-sdk-lambda
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '1'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '1'
84
+ - !ruby/object:Gem::Dependency
85
+ name: aws-sdk-iam
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '1'
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '1'
56
98
  - !ruby/object:Gem::Dependency
57
99
  name: bundler
58
100
  requirement: !ruby/object:Gem::Requirement
@@ -162,6 +204,7 @@ files:
162
204
  - bin/setup
163
205
  - lib/ruby_lambda.rb
164
206
  - lib/ruby_lambda/build.rb
207
+ - lib/ruby_lambda/deploy.rb
165
208
  - lib/ruby_lambda/error.rb
166
209
  - lib/ruby_lambda/execute.rb
167
210
  - lib/ruby_lambda/init.rb