jarbs 0.5.0

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: 8aee7bfc746ed5e58dfd6577850abab88c2c09d4
4
+ data.tar.gz: 5fb103e40bce30237c937ef469b35830a83253fc
5
+ SHA512:
6
+ metadata.gz: 5e9bb53cf84b6df0e0da406859c7a6ad48b8a94c531997888010154b86e39f6bfac5774372e7acea2e8eb9f777047959135dbace13ff78ff3d886588ee03591f
7
+ data.tar.gz: 12d91612386943a5172caee840032a3896283d85f479f646083dffd4d33c846625153a2db9fe7017ed3cf8fdeb51f496e98da6b6619acc7aaea67acc3663a4b9
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /demo/
11
+ /.env/
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
@@ -0,0 +1,82 @@
1
+ # JARBS
2
+
3
+ ## Opinionated Lambda Tooling
4
+
5
+ ![Jarbs](http://d.pr/i/12xTT/45aKDrvM+)
6
+
7
+ ## Install
8
+
9
+ Currently we distributed the `jarbs` runtime via gems hosted by RubyGems.org.
10
+
11
+ `gem install jarbs`
12
+
13
+ If this is a new machine or you haven't had to install any C extentions for Ruby yet, you may also need `cmake` before this gem will install: `brew install cmake`. We're looking at options for eliminating this step.
14
+
15
+ ## Usage
16
+
17
+ For the most up-to-date documentation and usage, run `jarbs -h`
18
+
19
+ ### Generate a new lambda project:
20
+
21
+ `lambda new my-function`
22
+
23
+ This produces:
24
+
25
+ ```
26
+ - my-function/
27
+ package.json (for build and dev deps)
28
+ - lambdas/
29
+ - my-function/
30
+ - src/
31
+ index.js (placeholder handler function)
32
+ package.json (for lambda dependencies)
33
+ ```
34
+
35
+ ### Generate another lambda in the same project
36
+
37
+ (while in the project folder created above):
38
+
39
+ `lambda new other-function`
40
+
41
+ Your project will then look like:
42
+
43
+ ```
44
+ - my-function/
45
+ package.json
46
+ - lambdas/
47
+ - my-function/
48
+ - src/
49
+ index.js
50
+ package.json
51
+ - other-function/
52
+ - src/
53
+ index.js
54
+ package.json
55
+ ```
56
+
57
+ ### Deploy to Lambda
58
+
59
+ `jarbs deploy my-function`
60
+
61
+ You can provide the ARN role via `--role` at invocation, or it will ask you for one during runtime. This will perform the following:
62
+
63
+ 1. Build code using [BabelJS](http://babeljs.io/) via the default `npm build:function` step as defined in the function's `package.json`. This build step also copies the compiled code from `src` to `dest`. If you customize the `npm build:function` step, the customization will also need to perform this same copy.
64
+ 2. Install npm dependecies via `npm install --production` in the `dest` directory.
65
+ 3. Package the `dest` dir as a zip archive (in memory).
66
+ 4. Upload to S3
67
+ 5. Destroy `dest` artifacts.
68
+
69
+ If you have already deployed this function to lambda before, it will update the code with your changes.
70
+
71
+ All functions are prefixed with the `--env` provided (i.e. 'dev', 'prod'). The env defaults to 'dev'.
72
+
73
+ ### Remove from Lambda
74
+
75
+ `jarbs rm my-function`
76
+
77
+ Will destroy the lambda function on AWS (will still leave files in your lambdas directory). You can specify multiple functions here if you wish.
78
+
79
+ ## License
80
+
81
+ *MIT*
82
+
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require 'jarbs/version'
3
+ # require "rake/testtask"
4
+
5
+ # Rake::TestTask.new(:test) do |t|
6
+ # t.libs << "test"
7
+ # t.libs << "lib"
8
+ # t.test_files = FileList['test/**/*_test.rb']
9
+ # end
10
+
11
+ # task :default => :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "jarbs"
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 "irb"
14
+ # IRB.start
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require "bundler/setup"
5
+ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
6
+
7
+ require "jarbs"
8
+
9
+ Jarbs::CLI.new.run
@@ -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,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'jarbs/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "jarbs"
8
+ spec.version = Jarbs::VERSION
9
+ spec.authors = ["Luke van der Hoeven"]
10
+ spec.email = ["hungerandthirst@gmail.com"]
11
+
12
+ spec.summary = %q{Jarbs: CLI Tooling for Lambda}
13
+ spec.description = %q{Jarbs: They took em.}
14
+ spec.homepage = "https://docs.articulate.zone/tools/jarbs.html"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.executables = %w{ jarbs }
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "commander"
21
+ spec.add_dependency "aws-sdk", "~> 2"
22
+ spec.add_dependency "rubyzip"
23
+ spec.add_dependency "rugged"
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.10"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "pry"
28
+ end
@@ -0,0 +1,82 @@
1
+ require 'rubygems'
2
+ require 'fileutils'
3
+ require 'commander'
4
+
5
+ require 'jarbs/version'
6
+ require 'jarbs/lambda'
7
+
8
+ module Jarbs
9
+ class CLI
10
+ include Commander::Methods
11
+
12
+ GLOBAL_DEFAULTS = { env: 'dev' }
13
+
14
+ def run
15
+ program :version, Jarbs::VERSION
16
+ program :description, 'Lambda Tooling'
17
+
18
+ global_option('-e', '--env ENV', String, 'Set deployment environment [Default to dev]')
19
+ global_option('-d', '--debug', 'Enable debug mode') { $debug = true }
20
+
21
+ command :new do |c|
22
+ c.syntax = 'jarbs new [options] name'
23
+ c.summary = "Generate a new lambda function skeleton"
24
+ c.option "-f", "--force", "Force overwrite of existing function definition"
25
+ c.action do |args, options|
26
+ name = args.shift || abort("Must provide a lambda name")
27
+ options.default GLOBAL_DEFAULTS
28
+
29
+ if Dir.exists? name
30
+ if options.force
31
+ FileUtils.rm_r name
32
+ else
33
+ abort("Function exists. Use the -f flag to force overwrite.")
34
+ end
35
+ end
36
+
37
+ # create project dir if doesn't exist yet
38
+ if !Dir.exists?('lambdas')
39
+ ProjectGenerator.new(name).generate
40
+ Dir.chdir name
41
+ end
42
+
43
+ Lambda.new(name, options).generate
44
+ end
45
+ end
46
+
47
+ command :deploy do |c|
48
+ c.syntax = 'jarbs deploy [options] directory'
49
+ c.summary = 'Deploy a lambda function to AWS'
50
+ c.option "--role [STRING]", String, "IAM role for Lambda execution"
51
+ c.action do |args, options|
52
+ name = args.shift || abort('Name argument required')
53
+ options.default GLOBAL_DEFAULTS
54
+
55
+ Lambda.new(name, options).deploy
56
+ end
57
+ end
58
+
59
+ command :rm do |c|
60
+ c.syntax = 'jarbs rm NAME [NAME...]'
61
+ c.summary = "Delete a lambda function"
62
+ c.action do |args, options|
63
+ name = args.shift || abort('Name argument required')
64
+ options.default GLOBAL_DEFAULTS
65
+
66
+ begin
67
+ args.each do |fn|
68
+ begin
69
+ Lambda.new(fn, options).delete
70
+ rescue Aws::Lambda::Errors::ResourceNotFoundException => e
71
+ say_error "Function \"#{fn}\" does not exists. Ignoring."
72
+ next
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ run!
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,10 @@
1
+ // Lambda will use `index.handler` as it's entrypoint.
2
+ // If you rename this file or the handler function,
3
+ // you will need to update the Lambda configs.
4
+
5
+ export function handler(event, context) {
6
+
7
+ // Your code here
8
+
9
+ context.done(null, { msg: "Hello from Lambda!" });
10
+ };
@@ -0,0 +1,45 @@
1
+ module Jarbs
2
+ class FunctionDefinition
3
+ attr_reader :env, :name, :root_path
4
+
5
+ def initialize(name, env='dev')
6
+ @env = env
7
+ @name = name
8
+ @root_path = File.join('lambdas', name)
9
+ end
10
+
11
+ def manifest
12
+ @manifest ||= JSON.parse File.read(manifest_file)
13
+ end
14
+
15
+ def manifest_file
16
+ File.join(source_path, 'package.json')
17
+ end
18
+
19
+ def env_name
20
+ "#{env}-#{name}"
21
+ end
22
+
23
+ def files
24
+ path = File.join build_path, "**", "*"
25
+ Dir.glob(path, File::FNM_DOTMATCH)
26
+ .reject {|f| File.directory? f }
27
+ end
28
+
29
+ def each_file(&block)
30
+ files.each {|file| yield basename(file), File.read(file) }
31
+ end
32
+
33
+ def build_path
34
+ File.join(root_path, 'dest')
35
+ end
36
+
37
+ def source_path
38
+ File.join(root_path, 'src')
39
+ end
40
+
41
+ def basename(filename)
42
+ filename.gsub(build_path + '/', '')
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,47 @@
1
+ module Jarbs
2
+ class FunctionGenerator
3
+ include Commander::UI
4
+ include ManifestHelpers
5
+
6
+ def initialize(function)
7
+ @function = function
8
+ end
9
+
10
+ def generate
11
+ say_ok "Generating function skeleton at #{@function.root_path}"
12
+
13
+ FileUtils.mkdir_p @function.source_path
14
+ install_manifest
15
+ install_handler
16
+ end
17
+
18
+ private
19
+
20
+ def install_manifest
21
+ package_manifest = {
22
+ name: @function.name,
23
+ version: '0.0.0',
24
+ description: ask('Function description: '),
25
+ author: whoami,
26
+ repository: {
27
+ type: 'git',
28
+ url: repo_url
29
+ },
30
+ license: 'UNLICENSED',
31
+ engines: {
32
+ node: '0.10.36'
33
+ },
34
+ main: 'index.js',
35
+ dependencies: {
36
+ 'babel-runtime' => '< 6'
37
+ }
38
+ }
39
+
40
+ write_package(package_manifest, @function.source_path)
41
+ end
42
+
43
+ def install_handler
44
+ FileUtils.cp File.join(File.dirname(__FILE__), 'fixtures', 'index.js'), @function.source_path
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,84 @@
1
+ require 'aws-sdk'
2
+
3
+ require 'jarbs/function_definition'
4
+ require 'jarbs/manifest_helpers'
5
+ require 'jarbs/project_generator'
6
+ require 'jarbs/function_generator'
7
+ require 'jarbs/node_build'
8
+ require 'jarbs/packager'
9
+
10
+ module Jarbs
11
+ class Lambda
12
+ include Commander::UI
13
+
14
+ def initialize(name, options)
15
+ @options = options
16
+
17
+ @function = FunctionDefinition.new(name, @options.env)
18
+ @client = Aws::Lambda::Client.new region: default_region
19
+ end
20
+
21
+ def generate
22
+ FunctionGenerator.new(@function).generate
23
+ end
24
+
25
+ def deploy
26
+ exists? ? update : create
27
+ end
28
+
29
+ def create
30
+ data = prepare_for_aws
31
+ role = @options[:role] || ask("IAM role for function: ")
32
+
33
+ say "Creating #{@function.env_name} on Lambda..."
34
+ @client.create_function function_name: @function.env_name,
35
+ runtime: 'nodejs',
36
+ handler: 'index.handler',
37
+ role: role,
38
+ memory_size: 128,
39
+ timeout: 10,
40
+ code: { zip_file: data }
41
+
42
+ say_ok "Complete!"
43
+ end
44
+
45
+ def update
46
+ data = prepare_for_aws
47
+
48
+ say "Updating #{@function.env_name} on Lambda..."
49
+ @client.update_function_code function_name: @function.env_name, zip_file: data
50
+ say_ok "Complete!"
51
+ end
52
+
53
+ def delete
54
+ res = @client.delete_function function_name: @function.env_name
55
+ say_ok "Removed #{@function.env_name}." if res.successful?
56
+ end
57
+
58
+ def info
59
+ @client.get_function(function_name: @function.env_name)
60
+ end
61
+
62
+ def exists?
63
+ true if info
64
+ rescue Aws::Lambda::Errors::ResourceNotFoundException => e
65
+ false
66
+ end
67
+
68
+ private
69
+
70
+ def prepare_for_aws
71
+ node = NodeBuild.new(@function)
72
+
73
+ node.npm_build
74
+ package = Packager.new(@function).package
75
+ ensure
76
+ node.clean
77
+ package
78
+ end
79
+
80
+ def default_region
81
+ `aws configure get region`.chomp
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,22 @@
1
+ require 'rugged'
2
+
3
+ module Jarbs
4
+ module ManifestHelpers
5
+
6
+ def write_package(manifest, path)
7
+ File.open(File.join(path, 'package.json'), 'w') do |f|
8
+ f.write JSON.pretty_generate(manifest)
9
+ end
10
+ end
11
+
12
+ def whoami
13
+ @whoami ||= `whoami`.chomp
14
+ end
15
+
16
+ def repo_url
17
+ Rugged::Repository.discover(".").remotes.first.url
18
+ rescue Rugged::RepositoryError => e
19
+ nil
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,38 @@
1
+ module Jarbs
2
+ class NodeBuild
3
+ include Commander::UI
4
+
5
+ def initialize(function)
6
+ @function = function
7
+ end
8
+
9
+ def npm_install(path, flags="")
10
+ run_in path, "npm install #{flags}"
11
+ end
12
+
13
+ def npm_build
14
+ say_ok 'Building function...'
15
+
16
+ # Copy source dir to build location and build in-place
17
+ FileUtils.cp_r @function.source_path, @function.build_path
18
+ abortable_run "npm run build:function -- --out-dir #{@function.build_path} #{@function.source_path}"
19
+
20
+ npm_install @function.build_path, '--production'
21
+ end
22
+
23
+ def clean
24
+ FileUtils.rm_r @function.build_path if Dir.exists?(@function.build_path)
25
+ end
26
+
27
+ private
28
+
29
+ def run_in(location, cmd)
30
+ Dir.chdir(location) { abortable_run(cmd) }
31
+ end
32
+
33
+ def abortable_run(cmd)
34
+ success = system(cmd)
35
+ abort("cpm runtime exited with non-zero status code: #{$?.exitstatus}") unless success
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,34 @@
1
+ require 'zip'
2
+
3
+ module Jarbs
4
+ class Packager
5
+ include Commander::UI
6
+
7
+ def initialize(function)
8
+ @function = function
9
+ end
10
+
11
+ def package
12
+ say_ok "Packaging..."
13
+
14
+ stream = Zip::OutputStream.write_buffer do |out|
15
+ @function.each_file do |filename, contents|
16
+ out.put_next_entry(filename)
17
+ out.write contents
18
+ end
19
+ end
20
+
21
+ write_zip(stream.string) if $debug
22
+
23
+ # return the generated zip data
24
+ stream.string
25
+ end
26
+
27
+ def write_zip(data)
28
+ zipname = File.join(@function.root_path, "#{@function.name}.zip")
29
+
30
+ File.open(zipname, 'w') {|zip| zip.write(data) }
31
+ say_warning "DEBUG: Output debug package to #{zipname}"
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,38 @@
1
+ module Jarbs
2
+ class ProjectGenerator
3
+ include ManifestHelpers
4
+
5
+ def initialize(name)
6
+ @name = name
7
+ end
8
+
9
+ def generate
10
+ FileUtils.mkdir @name
11
+
12
+ manifest = {
13
+ name: @name,
14
+ version: '0.0.0',
15
+ author: whoami,
16
+ repository: {
17
+ type: 'git',
18
+ url: repo_url
19
+ },
20
+ license: 'UNLICENSED',
21
+ engines: {
22
+ node: '0.10.36'
23
+ },
24
+ main: 'index.js',
25
+ scripts: {
26
+ 'build:function' => 'babel --optional runtime',
27
+ },
28
+ devDependencies: {
29
+ 'babel' => '< 6',
30
+ 'babel-runtime' => '< 6'
31
+ }
32
+ }
33
+
34
+ write_package(manifest, @name)
35
+ NodeBuild.new(nil).npm_install(@name)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,3 @@
1
+ module Jarbs
2
+ VERSION = "0.5.0"
3
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jarbs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - Luke van der Hoeven
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-11-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: commander
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: aws-sdk
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubyzip
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
+ - !ruby/object:Gem::Dependency
56
+ name: rugged
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.10'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.10'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '10.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '10.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: 'Jarbs: They took em.'
112
+ email:
113
+ - hungerandthirst@gmail.com
114
+ executables:
115
+ - jarbs
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - Gemfile
121
+ - Gemfile.lock
122
+ - README.md
123
+ - Rakefile
124
+ - bin/console
125
+ - bin/jarbs
126
+ - bin/setup
127
+ - jarbs.gemspec
128
+ - lib/jarbs.rb
129
+ - lib/jarbs/fixtures/index.js
130
+ - lib/jarbs/function_definition.rb
131
+ - lib/jarbs/function_generator.rb
132
+ - lib/jarbs/lambda.rb
133
+ - lib/jarbs/manifest_helpers.rb
134
+ - lib/jarbs/node_build.rb
135
+ - lib/jarbs/packager.rb
136
+ - lib/jarbs/project_generator.rb
137
+ - lib/jarbs/version.rb
138
+ homepage: https://docs.articulate.zone/tools/jarbs.html
139
+ licenses: []
140
+ metadata: {}
141
+ post_install_message:
142
+ rdoc_options: []
143
+ require_paths:
144
+ - lib
145
+ required_ruby_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ requirements: []
156
+ rubyforge_project:
157
+ rubygems_version: 2.4.8
158
+ signing_key:
159
+ specification_version: 4
160
+ summary: 'Jarbs: CLI Tooling for Lambda'
161
+ test_files: []