jarbs 0.5.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.
@@ -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: []