lamma 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ language: ruby
2
+ sudo: false
3
+ rvm:
4
+ - 2.3.3
5
+ - 2.4.0
6
+ addons:
7
+ code_climate:
8
+ repo_token:
9
+ secure: neUQqKyRYW9z4wBNqOzqMgRlKORVrLeczAd4ghoxdL3n+hez03Pqz3PesB5YU1jakxwPlY/f9DQOJDJOk8mNP84/McT3qeiXeAF+dVxnUmOj8GHdZlOgQi0b0b64zbAjGMI9sFtMwJ/ANx8GGCpOGa4PZDNhGddbDLVXKGJynvEC0iQ+t4nOXhUE+uOmaBeXNzmJ8bWdTwYDUvomNjOfWbZLqwOpHFHPFO2GSQ6s55i+oZcyvo+wPad6SwQf2YrJKX6a2MgZS0VDU2y9+SOVkZgXJA8+DUTqA25s8CEB1r0HadnPMI0f+666VNLn7Ds+pJBBQgEOxHTVA+WhV146tXX14ue5i08uwKjV5Uxg80m2uOt8OggMROpXNw2+oFwBG/oCuarbv/CCiF6V9NwKcD9O90ZJxvuc0OpJiQHPbPPLiegezavTlntY1gpz+Wpw294IbeYsH9cZKO913W3JFeOwYbEaVT/VMOmWkigv0WNQ+tX9xvvzQH536YRMfLz7NO0OM5myhBOrGr7Ui9xpRoq8O3p69ZLW0LDZN3NJUz/wkcz9eA4vqfPGu6d0mMrMPh/ymRKOqnaHNylHWhzf3bc6HGUyson0at7X6FlAAlok3G9Zi8VSMc6M1TYequeR7ByprvMscVIKiQjEmIkdmfLzcAu8u9/MaDrBNDjahoc=
10
+ script:
11
+ - bundle exec rake spec
12
+ cache: bundler
13
+ after_success:
14
+ - bundle exec codeclimate-test-reporter
15
+ deploy:
16
+ provider: rubygems
17
+ api_key:
18
+ secure: aN15UjA+CAG3k9v2AUgnEr4Lyg6ThB9cG2qB7hygU8CZ9ppBuQgGBHC3aSH0gP5jU7YRRli99wuEL5Pq1k97mxc5oOdQtpk5Br6dV7hByksImat6R1CWZPK0tC4VgPbFqTuTNt81ukXTYP8JJ1SJ9Z3gSXy4L62LJlhKpYKPA8ACYLdho/4nnbiMIWHnMUBEKhN2HqaIr/h87dsnJbm1fvVliOZnYFwXt2TeDTOEz+MLreJvTGYKUrV4yXLMsH68Nku07+785RWT39mYlxVg1t8Z41ScB0rAcGrk0UI/2PW6VkL9csKzCEj6PgbnBoZhIyXpNQrngSKkTjVB2Wpy9f0/NwzlfxoxhFjAuwkahXCNf6sGoYpm4iSY2Nz/riKBG/71fwSwrpE+/R7uzWZU/qFFOCpikp9EUQl3a6lhV2EM/z+yYel1Fsu3rZP//aOmQrIAxThndnHn3JGYHko6/lhaipqH8iBKbTMNgb//H9+Iy+cBWGO2KiwsfJN88jan/TeAWO6J1WGXT4PSPD6JmtE1ak4P2/KYNSWHUqsbRRgFAiHBGxOUkctqXh6ZhFep5BNpt9bQRtdRxlubZF+yAMbHS8HArL25zlBka6mHQ2GUFgM3KlKwyQ2UFNv1CzrJ56HtnpO4FvfGp30WFosBiUg5zjtEQ6zsnCvWi8qqCDU=
19
+ gem: lamma
20
+ on:
21
+ tags: true
22
+ repo: ayemos/lamma
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in lamma.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'simplecov', require: false
8
+ gem "codeclimate-test-reporter", "~> 1.0.0"
9
+ end
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 yuichiro-someya
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,76 @@
1
+ # Lamma
2
+ [![Gem Version](https://badge.fury.io/rb/lamma.svg)](https://badge.fury.io/rb/lamma)
3
+ [![Code Climate](https://codeclimate.com/github/ayemos/lamma/badges/gpa.svg)](https://codeclimate.com/github/ayemos/lamma)
4
+ [![Test Coverage](https://codeclimate.com/github/ayemos/lamma/badges/coverage.svg)](https://codeclimate.com/github/ayemos/lamma/coverage)
5
+ [![Issue Count](https://codeclimate.com/github/ayemos/lamma/badges/issue_count.svg)](https://codeclimate.com/github/ayemos/lamma)
6
+
7
+ It will help [Amazon Lambda](http://aws.amazon.com/lambda/) developer to,
8
+ - Create new function,
9
+ - Deploy current code,
10
+ - and to Rollback last deployment.
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'lamma'
18
+ ```
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install lamma
27
+
28
+ ## Configuration
29
+ The gem uses [aws-sdk-ruby](http://aws.amazon.com/sdk-for-ruby/) to get an access to AWS api-es.
30
+
31
+ ``` AWS_ACCESS_KEY_ID ``` and ``` AWS_SECRET_ACCESS_KEY ``` have to be set within your environment.
32
+
33
+ ```
34
+ export AWS_ACCESS_KEY_ID = [YOUR_AWS_ACCESS_KEY_ID]
35
+ export AWS_SECRET_ACCESS_KEY = [YOUR_AWS_SECRET_ACCESS_KEY]
36
+ ```
37
+
38
+ ## Usage & Basic Workflow
39
+
40
+ ### Create new Lambda Function
41
+ ```
42
+ lamma create my_function --runtime 'python2.7'
43
+ ```
44
+ ![create]()
45
+
46
+ ### Deploy current code to Remote
47
+
48
+ You have to be in a directory created by 'create' command with 'lamma.conf' file.
49
+
50
+ Make some change on nodejs/python2.7 function and
51
+
52
+ ```
53
+ lamma deploy production(or development)
54
+ ```
55
+ ![create]()
56
+ ![console]()
57
+
58
+ ### Rollback last deploy
59
+
60
+ ```
61
+ lamma rollback production(or development)
62
+ ```
63
+ ![before]()
64
+ ![after]()
65
+
66
+ ### Recommended setting
67
+ It is recommended to connect your lambda with an event source via PROD/DEV version aliases,
68
+ so that you can keep the mapping before/after the deployment/rollback.
69
+ ([see also](https://docs.aws.amazon.com/lambda/latest/dg/versioning-aliases.html))
70
+
71
+ End-to-end functionalities for
72
+ - Managing event-source-mappings,
73
+ - Creating IAM roles
74
+
75
+ will be supported in future release.
76
+
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "lamma"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "pry"
14
+ Pry.start
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,11 @@
1
+ import json
2
+
3
+ print('Loading function')
4
+
5
+ def lambda_handler(event, context):
6
+ #print("Received event: " + json.dumps(event, indent=2))
7
+ print("value1 = " + event['key1'])
8
+ print("value2 = " + event['key2'])
9
+ print("value3 = " + event['key3'])
10
+ return event['key1'] # Echo back the first key value
11
+ #raise Exception('Something went wrong')
File without changes
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ retried = false
4
+ begin
5
+ require 'lamma'
6
+ require 'lamma/cli'
7
+ rescue LoadError
8
+ $:.unshift File.expand_path(File.join(__dir__, '..', 'lib'))
9
+ if retried
10
+ raise
11
+ else
12
+ retried = true
13
+ retry
14
+ end
15
+ end
16
+
17
+ Lamma::CLI.start(ARGV)
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'lamma/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "lamma"
8
+ spec.version = Lamma::VERSION
9
+ spec.authors = ["Yuichiro Someya"]
10
+ spec.email = ["ayemos.y@gmail.com"]
11
+
12
+ spec.summary = %q{Deploy toolset for Amazon Lambda functions.}
13
+ spec.description = %q{Deploy toolset for Amazon Lambda functions..}
14
+ spec.homepage = "https://github.com/ayemos/Lamma"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.10"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "rspec", "~> 3"
25
+
26
+ spec.add_dependency "aws-sdk", "~> 2"
27
+ spec.add_dependency "thor", "~> 0.19"
28
+ spec.add_dependency "rubyzip", "~> 1.2"
29
+ end
@@ -0,0 +1,4 @@
1
+ module Lamma
2
+ DEFAULT_CONF_PATH = './lamma.yml'
3
+ LAST_DEPLOY_SUFFIX = 'LAMMA_LAST'
4
+ end
@@ -0,0 +1,74 @@
1
+ module Lamma
2
+ class Alias
3
+ attr_accessor :description, :version
4
+
5
+ def initialize(function, name, version=nil, description=nil)
6
+ @function = function
7
+ @name = name
8
+ @version = version
9
+ @description = description
10
+ end
11
+
12
+ def create
13
+ lambda_client.create_alias({
14
+ function_name: @function.name,
15
+ name: name, # 'name' indicates the self
16
+ function_version: @version,
17
+ description: description
18
+ })
19
+ end
20
+
21
+ def update
22
+ lambda_client.update_alias({
23
+ function_name: @function.name,
24
+ name: name, # 'name' indicates the self
25
+ function_version: @version,
26
+ description: description
27
+ })
28
+ end
29
+
30
+ def create_or_update
31
+ if remote_exists?
32
+ update
33
+ else
34
+ create
35
+ end
36
+ end
37
+
38
+ def name
39
+ @name.upcase
40
+ end
41
+
42
+ def remote_exists?
43
+ begin
44
+ lambda_client.get_alias({
45
+ function_name: @function.name,
46
+ name: name
47
+ })
48
+ rescue Aws::Lambda::Errors::ResourceNotFoundException
49
+ false
50
+ end
51
+ end
52
+
53
+ def remote_version
54
+ begin
55
+ lambda_client.get_alias({
56
+ function_name: @function.name,
57
+ name: name
58
+ }).function_version
59
+ rescue Aws::Lambda::Errors::ResourceNotFoundException
60
+ nil
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def description
67
+ @description ||= "Function alias #{name} managed by lamma"
68
+ end
69
+
70
+ def lambda_client
71
+ @lambda_client ||= Aws::Lambda::Client.new(region: @function.region)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,63 @@
1
+ require 'lamma'
2
+ require 'thor'
3
+
4
+ module Lamma
5
+ class CLI < Thor
6
+ class_option :verbose, aliases: '-v', type: :boolean
7
+ map '--version' => :print_version
8
+
9
+ desc 'list', 'List lambda functions in AWS'
10
+ def list
11
+ require 'lamma/cli/list'
12
+ List.new(options, self).run
13
+ end
14
+
15
+ desc 'show FUNCTION_NAME', 'Show detailed description of the function'
16
+ def show(function_name)
17
+ require 'lamma/cli/show'
18
+ Show.new(options, self).run
19
+ end
20
+
21
+ desc 'deploy', 'Upload local lambda function to AWS and deploy.'
22
+ method_option :path, aliases: '-p', type: :string
23
+ method_option :alias, aliases: '-a', type: :string
24
+ method_option :message, aliases: '-m', type: :string
25
+ def deploy
26
+ require 'lamma/cli/deploy'
27
+ Deploy.new(options, self).run
28
+ end
29
+
30
+ desc 'rollback', 'Rollback last deploy.'
31
+ method_option :path, aliases: '-p', type: :string
32
+ method_option :alias, aliases: '-a', type: :string
33
+ def rollback
34
+ require 'lamma/cli/rollback'
35
+ Rollback.new(options, self).run
36
+ end
37
+
38
+ desc 'create', 'Create new remote function.'
39
+ method_option :path, aliases: '-p', type: :string
40
+ def create
41
+ require 'lamma/cli/create'
42
+ Create.new(options, self).run
43
+ end
44
+
45
+ desc 'init FUNCTION_NAME', 'Initialize local function'
46
+ method_option :runtime, aliases: '-r', type: :string, required: true
47
+ def init(function_name)
48
+ require 'lamma/cli/init'
49
+ Init.new(options, function_name, self).run
50
+ end
51
+
52
+ desc "update", "Update function configuration and upload function"
53
+ def update
54
+ require 'lamma/cli/update'
55
+ Update.new(options, self).run
56
+ end
57
+
58
+ desc "--version", "print the version"
59
+ def print_version
60
+ puts Lamma::VERSION
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,16 @@
1
+ require 'lamma/cli'
2
+
3
+ module Lamma
4
+ class CLI::Create
5
+ def initialize(options, thor)
6
+ @options = options
7
+ @thor = thor
8
+ @conf_path = options[:path] || Lamma::DEFAULT_CONF_PATH
9
+ end
10
+
11
+ def run
12
+ f = Lamma::Function.new(@conf_path)
13
+ f.create
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,79 @@
1
+ require 'yaml'
2
+
3
+ require 'lamma'
4
+ require 'lamma/function'
5
+ require 'lamma/alias'
6
+
7
+ module Lamma
8
+ class CLI::Deploy
9
+ attr_reader :options, :thor
10
+
11
+ def initialize(options, thor)
12
+ @options = options
13
+ @thor = thor
14
+ @conf_path = options['path'] || Lamma::DEFAULT_CONF_PATH
15
+ end
16
+
17
+ def run
18
+ unless File.exists?(@conf_path)
19
+ abort("Config file #{@conf_path} is missing.")
20
+ end
21
+
22
+ f = Lamma::Function.new(@conf_path)
23
+
24
+ unless f.remote_exists?
25
+ thor.say("Function #{function.name} doesn't seem to be exist on remote.", :yellow)
26
+ y_or_n = thor.ask("Do you want me to create it? (y/n)", :yellow)
27
+
28
+ if y_or_n =~ /^[yY]/
29
+ f.create
30
+ end
31
+ end
32
+
33
+ f.update
34
+ new_version = f.publish_version(options['message']).version
35
+
36
+ if options['alias']
37
+ a = Lamma::Alias.new(f, options['alias'], new_version)
38
+
39
+ if a.remote_exists? && a.remote_version
40
+ last_version = a.remote_version
41
+ a.update
42
+ else
43
+ last_version = new_version
44
+
45
+ thor.say("Function alias #{a.name} doesn't seem to be exist on remote.", :yellow)
46
+ y_or_n = thor.ask("Do you want me to create it? (y/n)", :yellow)
47
+
48
+ if y_or_n =~ /^[yY]/
49
+ a.create
50
+ else
51
+ abort('Canceled')
52
+ end
53
+ end
54
+
55
+ la = Lamma::Alias.new(f, "#{@options['alias']}_#{Lamma::LAST_DEPLOY_SUFFIX}", last_version)
56
+ la.create_or_update
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def create_function(function, config)
63
+ begin
64
+ function.create_function(config['runtime'], config['role'])
65
+ rescue ArgumentError
66
+ thor.say("ArgumentError occured. You might need to specify role arn \
67
+ you want to pass to your function via 'lamma.conf' file or ENV['AWS_LAMBDA_IAM_ROLE'].", :red)
68
+ return
69
+ end
70
+ thor.say("Done.", :blue)
71
+ thor.say("Setting aliases.", :yellow)
72
+ first_version = function.publish_version.version
73
+ Lamma::Function::ENVIRONMENT_ALIAS_NAME_MAP.values.each do |alias_name|
74
+ function.create_alias(alias_name, first_version)
75
+ function.create_alias(alias_name << '_LAST', first_version)
76
+ end
77
+ end
78
+ end
79
+ end