jets 0.5.8 → 0.6.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile +2 -3
- data/jets.gemspec +1 -4
- data/lib/jets.rb +3 -2
- data/lib/jets/application.rb +18 -1
- data/lib/jets/aws_info.rb +36 -0
- data/lib/jets/aws_services.rb +5 -0
- data/lib/jets/builders/code_builder.rb +0 -1
- data/lib/jets/cfn/template_builders.rb +5 -2
- data/lib/jets/cfn/template_builders/api_gateway_builder.rb +2 -3
- data/lib/jets/cfn/template_builders/base_child_builder.rb +16 -0
- data/lib/jets/cfn/template_builders/function_properties/base_builder.rb +23 -1
- data/lib/jets/cfn/template_builders/iam_policy.rb +6 -0
- data/lib/jets/cfn/template_builders/iam_policy/application_policy.rb +18 -0
- data/lib/jets/cfn/template_builders/iam_policy/base_policy.rb +57 -0
- data/lib/jets/cfn/template_builders/iam_policy/class_policy.rb +20 -0
- data/lib/jets/cfn/template_builders/iam_policy/function_policy.rb +21 -0
- data/lib/jets/cfn/template_builders/interface.rb +1 -1
- data/lib/jets/cfn/template_builders/parent_builder.rb +4 -6
- data/lib/jets/cfn/template_builders/templates/minimal-stack.yml +0 -36
- data/lib/jets/cfn/template_mappers.rb +2 -0
- data/lib/jets/cfn/template_mappers/iam_policy.rb +6 -0
- data/lib/jets/cfn/template_mappers/iam_policy/application_policy_mapper.rb +28 -0
- data/lib/jets/cfn/template_mappers/iam_policy/base_policy_mapper.rb +44 -0
- data/lib/jets/cfn/template_mappers/iam_policy/class_policy_mapper.rb +32 -0
- data/lib/jets/cfn/template_mappers/iam_policy/function_policy_mapper.rb +32 -0
- data/lib/jets/cfn/template_mappers/lambda_function_mapper.rb +3 -1
- data/lib/jets/commands/build.rb +2 -2
- data/lib/jets/commands/call.rb +1 -1
- data/lib/jets/core.rb +5 -1
- data/lib/jets/internal/app/controllers/jets/public_controller.rb +1 -2
- data/lib/jets/internal/app/jobs/jets/preheat_job.rb +14 -0
- data/lib/jets/lambda/dsl.rb +20 -1
- data/lib/jets/lambda/task.rb +2 -1
- data/lib/jets/version.rb +1 -1
- metadata +13 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b156a3904d427d2d2604ad4026e069c6efe7a724c6c3937c9bd0a8cc28ecdda2
|
4
|
+
data.tar.gz: 4fb811e051ea4cf10dd5032a2b127a0b92b686d3e9818640fe8e10f2cc6b34a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c137bfe10a6a4c07af49d524a95374ca26c124b5367054015e709adaa200c748b2187b4275e69495cff5a0cef60c70e52e6abb8be81bd0a524953c96d7043b6a
|
7
|
+
data.tar.gz: e823f819bc813e3e78b99ca76c38aae10ee644178b73ad4728bc5bdea70818bfc544af116020e89c472d2cd5ac99fee79244e69fea2aacb26644a37e3fae9888
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,10 @@
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
|
5
5
|
|
6
|
+
## [0.6.0]
|
7
|
+
- fine grain iam policy abilities: pull request #13 from tongueroo/iam-policy
|
8
|
+
- changed quite a few logical ids in the CloudFormation templates
|
9
|
+
|
6
10
|
## [0.5.8]
|
7
11
|
- fix config.prewarm defaults
|
8
12
|
|
data/Gemfile
CHANGED
@@ -4,9 +4,8 @@ source "https://rubygems.org"
|
|
4
4
|
gemspec
|
5
5
|
|
6
6
|
# required here for specs
|
7
|
-
# TODO:
|
8
|
-
#
|
9
|
-
# jets/webpacker/middleware_setup.rb
|
7
|
+
# TODO: Only require webpacker in Gemfile of project if possible.
|
8
|
+
# Need both because of jets/application.rb and jets/webpacker/middleware_setup.rb
|
10
9
|
group :development, :test do
|
11
10
|
gem "webpacker", git: "https://github.com/tongueroo/webpacker.git", branch: "jets"
|
12
11
|
gem "rspec_junit_formatter"
|
data/jets.gemspec
CHANGED
@@ -31,8 +31,6 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.add_dependency "actionpack"
|
32
32
|
spec.add_dependency "activerecord"
|
33
33
|
spec.add_dependency "railties" # ActiveRecord database_tasks.rb require this
|
34
|
-
# TODO: only load the database adapters that the app uses, so generate this
|
35
|
-
# in the app's Gemfile
|
36
34
|
spec.add_dependency "dotenv"
|
37
35
|
|
38
36
|
spec.add_dependency "recursive-open-struct"
|
@@ -45,8 +43,7 @@ Gem::Specification.new do |spec|
|
|
45
43
|
spec.add_dependency "text-table"
|
46
44
|
spec.add_dependency "rack"
|
47
45
|
spec.add_dependency "json"
|
48
|
-
#
|
49
|
-
# in the app. but we want to have them so we can run specs.
|
46
|
+
# TODO: only load the database adapters that app's Gemfile instead of jets.gemspec
|
50
47
|
spec.add_dependency "pg", "=0.21"
|
51
48
|
|
52
49
|
spec.add_dependency "gems" # lambdagem dependency
|
data/lib/jets.rb
CHANGED
@@ -5,7 +5,7 @@ require "active_support/core_ext/string"
|
|
5
5
|
require "active_support/ordered_hash"
|
6
6
|
require "colorize"
|
7
7
|
require "fileutils"
|
8
|
-
require "pp" # TODO:
|
8
|
+
require "pp" # TODO: Remove pp after debugging
|
9
9
|
require "memoist"
|
10
10
|
|
11
11
|
module Jets
|
@@ -15,6 +15,7 @@ module Jets
|
|
15
15
|
autoload :CLI, "jets/cli"
|
16
16
|
autoload :Commands, "jets/commands"
|
17
17
|
|
18
|
+
autoload :AwsInfo, "jets/aws_info"
|
18
19
|
autoload :AwsServices, "jets/aws_services"
|
19
20
|
autoload :Builders, 'jets/builders'
|
20
21
|
autoload :Call, "jets/call"
|
@@ -57,7 +58,7 @@ if File.exist?("#{Jets.root}config/dynamodb.yml")
|
|
57
58
|
require "dynomite"
|
58
59
|
end
|
59
60
|
|
60
|
-
# https://makandracards.com/makandra/42521-detecting-if-a-ruby-gem-is-loaded
|
61
|
+
# Thanks: https://makandracards.com/makandra/42521-detecting-if-a-ruby-gem-is-loaded
|
61
62
|
# TODO: move require "pg" into loader class and abstract to support more gems
|
62
63
|
if File.exist?("#{Jets.root}config/database.yml")
|
63
64
|
require "active_record"
|
data/lib/jets/application.rb
CHANGED
@@ -82,9 +82,21 @@ class Jets::Application
|
|
82
82
|
# IE: With env_extra: project-dev-1
|
83
83
|
# Without env_extra: project-dev
|
84
84
|
config.short_env = ENV_MAP[Jets.env.to_sym] || Jets.env
|
85
|
-
config.project_namespace = [config.project_name, config.short_env, config.env_extra].compact.join('-')
|
86
85
|
# table_namespace does not have the env_extra, more common case desired.
|
87
86
|
config.table_namespace = [config.project_name, config.short_env].compact.join('-')
|
87
|
+
|
88
|
+
project_namespace = [config.project_name, config.short_env, config.env_extra].compact.join('-')
|
89
|
+
config.project_namespace = project_namespace
|
90
|
+
|
91
|
+
# config.iam_policy = ["logs2:*"]
|
92
|
+
# Must set defaul t iam_policy here instead of `def config` because we need access to
|
93
|
+
# the project_namespace and if we call it from `def config` we get an infinit loop
|
94
|
+
config.iam_policy = [{
|
95
|
+
sid: "Statement1",
|
96
|
+
action: ["logs:*"],
|
97
|
+
effect: "Allow",
|
98
|
+
resource: "arn:aws:logs:#{Jets.aws.region}:#{Jets.aws.account}:log-group:#{project_namespace}-*",
|
99
|
+
}]
|
88
100
|
end
|
89
101
|
|
90
102
|
# It is pretty easy to attempt to set environment variables without
|
@@ -124,4 +136,9 @@ class Jets::Application
|
|
124
136
|
require routes_file if File.exist?(routes_file)
|
125
137
|
end
|
126
138
|
|
139
|
+
def aws
|
140
|
+
Jets::AwsInfo.new
|
141
|
+
end
|
142
|
+
memoize :aws
|
143
|
+
|
127
144
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
module Jets
|
3
|
+
class AwsInfo
|
4
|
+
extend Memoist
|
5
|
+
include AwsServices
|
6
|
+
|
7
|
+
def region
|
8
|
+
return 'us-east-1' if ENV['TEST']
|
9
|
+
|
10
|
+
region = nil
|
11
|
+
|
12
|
+
# First try to get it from the ~/.aws/config
|
13
|
+
region = `aws configure get region`.strip rescue nil
|
14
|
+
return region if region
|
15
|
+
|
16
|
+
# Second try the metadata endpoint, should be available on AWS Lambda environment
|
17
|
+
# https://stackoverflow.com/questions/4249488/find-region-from-within-an-ec2-instance
|
18
|
+
begin
|
19
|
+
az = `curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone`
|
20
|
+
region = az.strip.chop # remove last char
|
21
|
+
rescue
|
22
|
+
end
|
23
|
+
return region if region
|
24
|
+
|
25
|
+
ENV['JETS_AWS_REGION'] || 'us-east-1' # default if all else fails
|
26
|
+
end
|
27
|
+
memoize :region
|
28
|
+
|
29
|
+
# aws sts get-caller-identity
|
30
|
+
def account
|
31
|
+
return '123456789' if ENV['TEST']
|
32
|
+
sts.get_caller_identity.account
|
33
|
+
end
|
34
|
+
memoize :account
|
35
|
+
end
|
36
|
+
end
|
data/lib/jets/aws_services.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "aws-sdk-s3"
|
2
2
|
require "aws-sdk-cloudformation"
|
3
3
|
require "aws-sdk-lambda"
|
4
|
+
require "aws-sdk-sts"
|
4
5
|
|
5
6
|
module Jets::AwsServices
|
6
7
|
def s3
|
@@ -19,6 +20,10 @@ module Jets::AwsServices
|
|
19
20
|
@lambda ||= Aws::Lambda::Client.new
|
20
21
|
end
|
21
22
|
|
23
|
+
def sts
|
24
|
+
@sts ||= Aws::STS::Client.new
|
25
|
+
end
|
26
|
+
|
22
27
|
def stack_exists?(stack_name)
|
23
28
|
return false if ENV['TEST']
|
24
29
|
|
@@ -359,7 +359,6 @@ EOL
|
|
359
359
|
md = spec.source.to_s.match(/@(\w+)\)/)
|
360
360
|
git_sha = md[1]
|
361
361
|
end
|
362
|
-
puts "git_shas #{git_shas.inspect}"
|
363
362
|
|
364
363
|
# IE: /tmp/jets/demo/cache/bundled/gems/ruby/2.5.0/bundler/gems/webpacker-a8c46614c675
|
365
364
|
Dir.glob("#{cache_area}/bundled/gems/ruby/2.5.0/bundler/gems/*").each do |path|
|
@@ -2,6 +2,7 @@ require 'active_support/core_ext/hash'
|
|
2
2
|
require 'yaml'
|
3
3
|
|
4
4
|
class Jets::Cfn
|
5
|
+
# TODO: Refactor builder classes. They all work slightly differently.
|
5
6
|
class TemplateBuilders
|
6
7
|
autoload :Interface, "jets/cfn/template_builders/interface"
|
7
8
|
autoload :ParentBuilder, "jets/cfn/template_builders/parent_builder"
|
@@ -15,7 +16,9 @@ class Jets::Cfn
|
|
15
16
|
|
16
17
|
autoload :ApiGatewayBuilder, "jets/cfn/template_builders/api_gateway_builder"
|
17
18
|
autoload :ApiGatewayDeploymentBuilder, "jets/cfn/template_builders/api_gateway_deployment_builder"
|
18
|
-
|
19
|
-
|
19
|
+
|
20
|
+
# separate beasts:
|
21
|
+
autoload :FunctionProperties, "jets/cfn/template_builders/function_properties" # sort of a builder
|
22
|
+
autoload :IamPolicy, "jets/cfn/template_builders/iam_policy" # resource only
|
20
23
|
end
|
21
24
|
end
|
@@ -43,9 +43,8 @@ class Jets::Cfn::TemplateBuilders
|
|
43
43
|
# Adds route related Resources and Outputs
|
44
44
|
def add_gateway_routes
|
45
45
|
# The routes required a Gateway Resource to contain them.
|
46
|
-
# TODO: outputing all routes in 1 template will hit the 60 routes limit
|
47
|
-
# Will have to either output them as a joined string or
|
48
|
-
# break this up to multiple tempaltes.
|
46
|
+
# TODO: Support more routes. Right now outputing all routes in 1 template will hit the 60 routes limit.
|
47
|
+
# Will have to either output them as a joined string or break this up to multiple tempaltes.
|
49
48
|
# http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html
|
50
49
|
# Outputs: Maximum number of outputs that you can declare in your AWS CloudFormation template. 60 outputs
|
51
50
|
# Output name: Maximum size of an output name. 255 characters.
|
@@ -20,8 +20,10 @@ class Jets::Cfn::TemplateBuilders
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def add_functions
|
23
|
+
add_class_iam_policy if @app_klass.class_iam_policy
|
23
24
|
@app_klass.tasks.each do |task|
|
24
25
|
add_function(task)
|
26
|
+
add_iam_policy(task) if task.iam_policy
|
25
27
|
end
|
26
28
|
end
|
27
29
|
|
@@ -34,5 +36,19 @@ class Jets::Cfn::TemplateBuilders
|
|
34
36
|
logical_id = builder.map.logical_id
|
35
37
|
add_resource(logical_id, "AWS::Lambda::Function", builder.properties)
|
36
38
|
end
|
39
|
+
|
40
|
+
def add_class_iam_policy
|
41
|
+
map = Jets::Cfn::TemplateMappers::IamPolicy::ClassPolicyMapper.new(@app_klass)
|
42
|
+
logical_id = map.logical_id
|
43
|
+
properties = map.properties
|
44
|
+
add_resource(logical_id, "AWS::IAM::Role", properties)
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_iam_policy(task)
|
48
|
+
map = Jets::Cfn::TemplateMappers::IamPolicy::FunctionPolicyMapper.new(task)
|
49
|
+
logical_id = map.logical_id
|
50
|
+
properties = map.properties
|
51
|
+
add_resource(logical_id, "AWS::IAM::Role", properties)
|
52
|
+
end
|
37
53
|
end
|
38
54
|
end
|
@@ -79,10 +79,19 @@ module Jets::Cfn::TemplateBuilders::FunctionProperties
|
|
79
79
|
# class_timeout 22
|
80
80
|
# ...
|
81
81
|
# end
|
82
|
+
#
|
83
|
+
# Also handles iam policy override at the class level. Example:
|
84
|
+
#
|
85
|
+
# class_iam_policy("logs:*")
|
86
|
+
#
|
82
87
|
def class_properties
|
83
88
|
# klass is PostsController, HardJob, GameRule, Hello or HelloFunction
|
84
89
|
klass = Jets::Klass.from_task(@task)
|
85
90
|
class_properties = klass.class_properties
|
91
|
+
if klass.class_iam_policy
|
92
|
+
map = Jets::Cfn::TemplateMappers::IamPolicy::ClassPolicyMapper.new(klass)
|
93
|
+
class_properties[:Role] = "!GetAtt #{map.logical_id}.Arn"
|
94
|
+
end
|
86
95
|
Pascalize.pascalize(class_properties.deep_stringify_keys)
|
87
96
|
end
|
88
97
|
|
@@ -93,8 +102,21 @@ module Jets::Cfn::TemplateBuilders::FunctionProperties
|
|
93
102
|
# def index
|
94
103
|
# ...
|
95
104
|
# end
|
105
|
+
#
|
106
|
+
# Also handles iam policy override at the function level. Example:
|
107
|
+
#
|
108
|
+
# iam_policy("ec2:*")
|
109
|
+
# def new
|
110
|
+
# render json: params.merge(action: "new")
|
111
|
+
# end
|
112
|
+
#
|
96
113
|
def function_properties
|
97
|
-
|
114
|
+
properties = @task.properties
|
115
|
+
if @task.iam_policy
|
116
|
+
map = Jets::Cfn::TemplateMappers::IamPolicy::FunctionPolicyMapper.new(@task)
|
117
|
+
properties[:Role] = "!GetAtt #{map.logical_id}.Arn"
|
118
|
+
end
|
119
|
+
Pascalize.pascalize(properties.deep_stringify_keys)
|
98
120
|
end
|
99
121
|
|
100
122
|
def env_file_properties
|
@@ -0,0 +1,6 @@
|
|
1
|
+
module Jets::Cfn::TemplateBuilders::IamPolicy
|
2
|
+
autoload :ApplicationPolicy, "jets/cfn/template_builders/iam_policy/application_policy"
|
3
|
+
autoload :BasePolicy, "jets/cfn/template_builders/iam_policy/base_policy"
|
4
|
+
autoload :ClassPolicy, "jets/cfn/template_builders/iam_policy/class_policy"
|
5
|
+
autoload :FunctionPolicy, "jets/cfn/template_builders/iam_policy/function_policy"
|
6
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Implements:
|
2
|
+
# initialize
|
3
|
+
# policy_name
|
4
|
+
#
|
5
|
+
module Jets::Cfn::TemplateBuilders::IamPolicy
|
6
|
+
class ApplicationPolicy < BasePolicy
|
7
|
+
def initialize
|
8
|
+
setup
|
9
|
+
@definitions = Jets.config.iam_policy || [] # config.iam_policy contains definitions
|
10
|
+
end
|
11
|
+
|
12
|
+
# Example: PostsControllerPolicy or SleepJobPolicy
|
13
|
+
# Note: There is no "method" in the name
|
14
|
+
def policy_name
|
15
|
+
"ApplicationPolicy"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Classes that inherit this Base class should implement:
|
2
|
+
#
|
3
|
+
# initialize - should call setup in it
|
4
|
+
# policy_name
|
5
|
+
#
|
6
|
+
module Jets::Cfn::TemplateBuilders::IamPolicy
|
7
|
+
class BasePolicy
|
8
|
+
extend Memoist
|
9
|
+
|
10
|
+
attr_reader :definitions
|
11
|
+
# Not using initialize because method signature is different
|
12
|
+
def setup
|
13
|
+
# empty starting policy that will be changed
|
14
|
+
@policy = {
|
15
|
+
"Version" => "2012-10-17",
|
16
|
+
"Statement" => []
|
17
|
+
}
|
18
|
+
# https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_sid.html
|
19
|
+
@sid = 0 # counter
|
20
|
+
end
|
21
|
+
|
22
|
+
def policy_document
|
23
|
+
definitions.map { |definition| standardize(definition) }
|
24
|
+
# Thanks: https://www.mnishiguchi.com/2017/11/29/rails-hash-camelize-and-underscore-keys/
|
25
|
+
@policy.deep_transform_keys! { |key| key.to_s.camelize }
|
26
|
+
end
|
27
|
+
memoize :policy_document # only process policy_document once
|
28
|
+
|
29
|
+
def standardize(definition)
|
30
|
+
@sid += 1
|
31
|
+
case definition
|
32
|
+
when String
|
33
|
+
@policy["Statement"] << {
|
34
|
+
sid: "Stmt#{@sid}",
|
35
|
+
action: [definition],
|
36
|
+
effect: "Allow",
|
37
|
+
resource: "*",
|
38
|
+
}
|
39
|
+
when Hash
|
40
|
+
definition = definition.stringify_keys
|
41
|
+
if definition.key?("Version") # special case where we replace the policy entirely
|
42
|
+
@policy = definition
|
43
|
+
else
|
44
|
+
@policy["Statement"] << definition
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Need to underscore and then classify again for this case:
|
50
|
+
# Jets::PreheatJob_policy => JetsPreheatJobPolicy
|
51
|
+
# Or else you we get this:
|
52
|
+
# Jets::PreheatJob_policy => JetsPreheatjobPolicy
|
53
|
+
def classify_name(text)
|
54
|
+
text.gsub('::','_').underscore.classify
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Implements:
|
2
|
+
# initialize
|
3
|
+
# policy_name
|
4
|
+
#
|
5
|
+
module Jets::Cfn::TemplateBuilders::IamPolicy
|
6
|
+
class ClassPolicy < BasePolicy
|
7
|
+
def initialize(app_class)
|
8
|
+
setup
|
9
|
+
@app_class = app_class
|
10
|
+
# IE: @app_class: PostsController, HardJob, Hello, HelloFunction
|
11
|
+
@definitions = app_class.class_iam_policy || [] # class_iam_policy contains definitions
|
12
|
+
end
|
13
|
+
|
14
|
+
# Example: PostsControllerPolicy or SleepJobPolicy
|
15
|
+
# Note: There is no "method" in the name
|
16
|
+
def policy_name
|
17
|
+
classify_name("#{@app_class}_policy")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Implements:
|
2
|
+
# initialize
|
3
|
+
# policy_name
|
4
|
+
#
|
5
|
+
module Jets::Cfn::TemplateBuilders::IamPolicy
|
6
|
+
class FunctionPolicy < BasePolicy
|
7
|
+
def initialize(task)
|
8
|
+
setup
|
9
|
+
@task = task
|
10
|
+
@app_class = task.class_name.to_s
|
11
|
+
# IE: @app_class: PostsController, HardJob, Hello, HelloFunction
|
12
|
+
|
13
|
+
@definitions = task.iam_policy || [] # iam_policy contains definitions
|
14
|
+
end
|
15
|
+
|
16
|
+
# Example: PostsControllerIndexPolicy or SleepJobPerformPolicy
|
17
|
+
def policy_name
|
18
|
+
classify_name("#{@app_class}_#{@task.meth}_policy")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -43,7 +43,7 @@ class Jets::Cfn::TemplateBuilders
|
|
43
43
|
results.join("\n") + "\n"
|
44
44
|
end
|
45
45
|
|
46
|
-
# add_resource handles an options Hash with both only
|
46
|
+
# add_resource handles an options Hash with both only Properties
|
47
47
|
# and also one with a nested Properties.
|
48
48
|
|
49
49
|
# Example:
|
@@ -32,9 +32,11 @@ class Jets::Cfn::TemplateBuilders
|
|
32
32
|
}
|
33
33
|
rendered_result = Jets::Erb.result(path, variables)
|
34
34
|
minimal_template = YAML.load(rendered_result)
|
35
|
-
|
36
|
-
# minimal_template = YAML.load(IO.read(path))
|
37
35
|
@template.deep_merge!(minimal_template)
|
36
|
+
|
37
|
+
# Add application-wide IAM policy from Jets.config.iam_role
|
38
|
+
map = Jets::Cfn::TemplateMappers::IamPolicy::ApplicationPolicyMapper.new
|
39
|
+
add_resource(map.logical_id, "AWS::IAM::Role", map.properties)
|
38
40
|
end
|
39
41
|
|
40
42
|
def add_child_resources
|
@@ -48,7 +50,6 @@ class Jets::Cfn::TemplateBuilders
|
|
48
50
|
#
|
49
51
|
# map = Jets::Cfn::TemplateMappers::ControllerMapper.new(path, s3_bucket)
|
50
52
|
# map = Jets::Cfn::TemplateMappers::JobMapper.new(path, s3_bucket)
|
51
|
-
# map = Jets::Cfn::TemplateMappers::FunctionMapper.new(path, s3_bucket)
|
52
53
|
#
|
53
54
|
mapper_class_name = File.basename(path, '.yml').split('_').last
|
54
55
|
mapper_class_name = mapper_class_name.classify
|
@@ -68,9 +69,6 @@ class Jets::Cfn::TemplateBuilders
|
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
71
|
-
# Each shared stacks has different logic.
|
72
|
-
# Handle in ugly case statement until we see the common patterns between them.
|
73
|
-
# TODO: clean up the add_shared_stack logical after we figure out the common interface pattern
|
74
72
|
def add_api_gateway
|
75
73
|
path = "#{Jets.config.project_namespace}-api-gateway.yml"
|
76
74
|
map = Jets::Cfn::TemplateMappers::ApiGatewayMapper.new(path, @options[:s3_bucket])
|
@@ -2,42 +2,6 @@
|
|
2
2
|
Resources:
|
3
3
|
S3Bucket:
|
4
4
|
Type: AWS::S3::Bucket
|
5
|
-
IamRole:
|
6
|
-
Type: AWS::IAM::Role
|
7
|
-
Properties:
|
8
|
-
AssumeRolePolicyDocument:
|
9
|
-
Version: '2012-10-17'
|
10
|
-
Statement:
|
11
|
-
- Effect: Allow
|
12
|
-
Principal:
|
13
|
-
Service:
|
14
|
-
- lambda.amazonaws.com
|
15
|
-
Action:
|
16
|
-
- sts:AssumeRole
|
17
|
-
Policies:
|
18
|
-
- PolicyName: <%= @policy_name %>
|
19
|
-
PolicyDocument:
|
20
|
-
Version: '2012-10-17'
|
21
|
-
Statement:
|
22
|
-
- Effect: Allow
|
23
|
-
Action:
|
24
|
-
- logs:*
|
25
|
-
Resource: '*'
|
26
|
-
# TODO: Make IAM permissions more fine grain for mimimal stack
|
27
|
-
# - Fn::Sub: arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/quiz-dev-hello:*:*
|
28
|
-
# - Fn::Sub: arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/quiz-dev-quiz:*:*
|
29
|
-
# TODO: Allow hook so user can configure IAM themselves and support managed polices
|
30
|
-
- Effect: Allow
|
31
|
-
Action:
|
32
|
-
- dynamodb:*
|
33
|
-
Resource: "*"
|
34
|
-
# required for PreheatJob which calls the other lambda functions repeatedly
|
35
|
-
- Effect: Allow
|
36
|
-
Action:
|
37
|
-
- lambda:*
|
38
|
-
Resource: "*"
|
39
|
-
Path: "/"
|
40
|
-
RoleName: <%= @role_name %>
|
41
5
|
Outputs:
|
42
6
|
S3Bucket:
|
43
7
|
Value: "!Ref S3Bucket" # not a valid cfn notation, surrounding double quotes is handled by post processing.
|
@@ -0,0 +1,6 @@
|
|
1
|
+
module Jets::Cfn::TemplateMappers::IamPolicy
|
2
|
+
autoload :ApplicationPolicyMapper, "jets/cfn/template_mappers/iam_policy/application_policy_mapper"
|
3
|
+
autoload :BasePolicyMapper, "jets/cfn/template_mappers/iam_policy/base_policy_mapper"
|
4
|
+
autoload :ClassPolicyMapper, "jets/cfn/template_mappers/iam_policy/class_policy_mapper"
|
5
|
+
autoload :FunctionPolicyMapper, "jets/cfn/template_mappers/iam_policy/function_policy_mapper"
|
6
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Implements:
|
2
|
+
#
|
3
|
+
# initialize
|
4
|
+
# iam_policy
|
5
|
+
# logical_id
|
6
|
+
# role_name
|
7
|
+
#
|
8
|
+
module Jets::Cfn::TemplateMappers::IamPolicy
|
9
|
+
class ApplicationPolicyMapper < BasePolicyMapper
|
10
|
+
def initialize; end # does nothing
|
11
|
+
|
12
|
+
def iam_policy
|
13
|
+
Jets::Cfn::TemplateBuilders::IamPolicy::ApplicationPolicy.new
|
14
|
+
end
|
15
|
+
memoize :iam_policy
|
16
|
+
|
17
|
+
# Example: PostsControllerLambdaFunction
|
18
|
+
# Note there are is no "Show" action in the name
|
19
|
+
def logical_id
|
20
|
+
"IamRole" # very simple logical ideal for the application-wide logical id
|
21
|
+
end
|
22
|
+
|
23
|
+
# There should be namespace in the role_name.
|
24
|
+
def role_name
|
25
|
+
"#{namespace}_application_iam_role".underscore.dasherize
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Class that inherits this base class should implement:
|
2
|
+
#
|
3
|
+
# initialize
|
4
|
+
# iam_policy
|
5
|
+
# logical_id
|
6
|
+
# role_name
|
7
|
+
#
|
8
|
+
module Jets::Cfn::TemplateMappers::IamPolicy
|
9
|
+
class BasePolicyMapper
|
10
|
+
extend Memoist
|
11
|
+
|
12
|
+
def properties
|
13
|
+
properties = {
|
14
|
+
AssumeRolePolicyDocument: {
|
15
|
+
Version: "2012-10-17",
|
16
|
+
Statement: [{
|
17
|
+
Effect: "Allow",
|
18
|
+
Principal: {Service: ["lambda.amazonaws.com"]},
|
19
|
+
Action: ["sts:AssumeRole"]}
|
20
|
+
]},
|
21
|
+
Path: "/"
|
22
|
+
}
|
23
|
+
properties[:Policies] = [
|
24
|
+
PolicyName: iam_policy.policy_name,
|
25
|
+
PolicyDocument: iam_policy.policy_document,
|
26
|
+
]
|
27
|
+
properties[:RoleName] = role_name
|
28
|
+
properties.deep_stringify_keys!
|
29
|
+
properties
|
30
|
+
end
|
31
|
+
|
32
|
+
def namespace
|
33
|
+
Jets.config.project_namespace.underscore
|
34
|
+
end
|
35
|
+
|
36
|
+
# Need to underscore and then classify again for this case:
|
37
|
+
# Jets::PreheatJob_policy => JetsPreheatJobPolicy
|
38
|
+
# Or else you we get this:
|
39
|
+
# Jets::PreheatJob_policy => JetsPreheatjobPolicy
|
40
|
+
def classify_name(text)
|
41
|
+
text.gsub('::','_').underscore.classify
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Implements:
|
2
|
+
#
|
3
|
+
# initialize
|
4
|
+
# iam_policy
|
5
|
+
# logical_id
|
6
|
+
# role_name
|
7
|
+
#
|
8
|
+
module Jets::Cfn::TemplateMappers::IamPolicy
|
9
|
+
class ClassPolicyMapper < BasePolicyMapper
|
10
|
+
def initialize(app_class)
|
11
|
+
@app_class = app_class
|
12
|
+
# IE: @app_class: PostsController, HardJob, Hello, HelloFunction
|
13
|
+
end
|
14
|
+
|
15
|
+
def iam_policy
|
16
|
+
Jets::Cfn::TemplateBuilders::IamPolicy::ClassPolicy.new(@app_class)
|
17
|
+
end
|
18
|
+
memoize :iam_policy
|
19
|
+
|
20
|
+
# Example: PostsControllerLambdaFunction
|
21
|
+
# Note there are is no "Show" action in the name
|
22
|
+
# There should be no namespace in the logical_id.
|
23
|
+
def logical_id
|
24
|
+
classify_name("#{@app_class}_iam_role")
|
25
|
+
end
|
26
|
+
|
27
|
+
# There should be namespace in the role_name.
|
28
|
+
def role_name
|
29
|
+
classify_name("#{namespace}_#{@app_class}_iam_role").underscore.dasherize
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Implements:
|
2
|
+
#
|
3
|
+
# initialize
|
4
|
+
# iam_policy
|
5
|
+
# logical_id
|
6
|
+
# role_name
|
7
|
+
#
|
8
|
+
module Jets::Cfn::TemplateMappers::IamPolicy
|
9
|
+
class FunctionPolicyMapper < BasePolicyMapper
|
10
|
+
def initialize(task)
|
11
|
+
@task = task
|
12
|
+
@app_class = task.class_name.to_s
|
13
|
+
# IE: @app_class: PostsController, HardJob, Hello, HelloFunction
|
14
|
+
end
|
15
|
+
|
16
|
+
def iam_policy
|
17
|
+
Jets::Cfn::TemplateBuilders::IamPolicy::FunctionPolicy.new(@task)
|
18
|
+
end
|
19
|
+
memoize :iam_policy
|
20
|
+
|
21
|
+
# Example: PostsControllerShowLambdaFunction
|
22
|
+
# There should be no namespace in the logical_id.
|
23
|
+
def logical_id
|
24
|
+
classify_name("#{@app_class}_#{@task.meth}_iam_role")
|
25
|
+
end
|
26
|
+
|
27
|
+
# There should be namespace in the role_name.
|
28
|
+
def role_name
|
29
|
+
classify_name("#{namespace}_#{@app_class}_#{@task.meth}_iam_role").underscore.dasherize
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -13,7 +13,9 @@ class Jets::Cfn::TemplateMappers
|
|
13
13
|
|
14
14
|
def environment
|
15
15
|
env = Jets.config.environment ? Jets.config.environment.to_h : {}
|
16
|
-
|
16
|
+
jets_env_options = {JETS_ENV: Jets.env.to_s}
|
17
|
+
jets_env_options[:JETS_ENV_EXTRA] = Jets.config.env_extra if Jets.config.env_extra
|
18
|
+
env.deep_merge(jets_env_options)
|
17
19
|
end
|
18
20
|
|
19
21
|
# Example: PostsControllerIndex or SleepJobPerform
|
data/lib/jets/commands/build.rb
CHANGED
@@ -41,7 +41,7 @@ module Jets::Commands
|
|
41
41
|
|
42
42
|
def build_all_templates
|
43
43
|
clean_templates
|
44
|
-
# TODO: move this
|
44
|
+
# TODO: Maybe move this tbuild.rb template related logic to cfn/builder.rb
|
45
45
|
## CloudFormation templates
|
46
46
|
puts "Building Lambda functions as CloudFormation templates."
|
47
47
|
# 1. Shared templates - child templates needs them
|
@@ -107,7 +107,7 @@ module Jets::Commands
|
|
107
107
|
# Crucial that the Dir.pwd is in the tmp_app_root because for
|
108
108
|
# because Jets.boot set ups autoload_paths and this is how project
|
109
109
|
# classes are loaded.
|
110
|
-
# TODO: rework code so
|
110
|
+
# TODO: rework code so that Dir.pwd does not have to be in tmp_app_root for build to work.
|
111
111
|
def self.app_files
|
112
112
|
paths = []
|
113
113
|
expression = "#{Jets.root}app/**/**/*.rb"
|
data/lib/jets/commands/call.rb
CHANGED
@@ -146,9 +146,9 @@ class Jets::Commands::Call
|
|
146
146
|
puts "Pro tip: The Lambda Console Link to the #{function_name} function has been added to your clipboard." unless @options[:mute]
|
147
147
|
end
|
148
148
|
|
149
|
+
# TODO: Hook client_context up and maek sure it works. Think I've figure out how to sign client_context below.
|
149
150
|
# Client context must be a valid Base64-encoded JSON object
|
150
151
|
# Example: http://docs.aws.amazon.com/mobileanalytics/latest/ug/PutEvents.html
|
151
|
-
# TODO: figure out how to sign client_context
|
152
152
|
def client_context
|
153
153
|
context = {
|
154
154
|
"client" => {
|
data/lib/jets/core.rb
CHANGED
@@ -23,6 +23,10 @@ module Jets::Core
|
|
23
23
|
application.config
|
24
24
|
end
|
25
25
|
|
26
|
+
def aws
|
27
|
+
application.aws
|
28
|
+
end
|
29
|
+
|
26
30
|
# Load all application base classes and project classes
|
27
31
|
def boot
|
28
32
|
Jets::Booter.boot!
|
@@ -77,7 +81,7 @@ module Jets::Core
|
|
77
81
|
def version
|
78
82
|
Jets::VERSION
|
79
83
|
end
|
80
|
-
|
84
|
+
|
81
85
|
def eager_load!
|
82
86
|
Dir.glob("#{Jets.root}app/**/*.rb").select do |path|
|
83
87
|
next if !File.file?(path) or path =~ %r{/javascript/} or path =~ %r{/views/}
|
@@ -2,8 +2,7 @@ require "rack/mime"
|
|
2
2
|
|
3
3
|
# Works for utf8 text files.
|
4
4
|
# TODO: Add support to public_controller for binary data like images.
|
5
|
-
# Tricky because API Gateway is not respecting the Accept header
|
6
|
-
# same way as browsers.
|
5
|
+
# Tricky because API Gateway is not respecting the Accept header the same way as browsers.
|
7
6
|
class Jets::PublicController < Jets::Controller::Base
|
8
7
|
layout false
|
9
8
|
internal true
|
@@ -7,6 +7,20 @@ class Jets::PreheatJob < ApplicationJob
|
|
7
7
|
|
8
8
|
class_timeout 30
|
9
9
|
class_memory 1024
|
10
|
+
class_iam_policy(
|
11
|
+
{
|
12
|
+
sid: "Statement1",
|
13
|
+
action: ["logs:*"],
|
14
|
+
effect: "Allow",
|
15
|
+
resource: "arn:aws:logs:#{Jets.aws.region}:#{Jets.aws.account}:log-group:#{Jets.config.project_namespace}-*",
|
16
|
+
},
|
17
|
+
{
|
18
|
+
sid: "Statement2",
|
19
|
+
action: ["lambda:InvokeFunction", "lambda:InvokeAsync"],
|
20
|
+
effect: "Allow",
|
21
|
+
resource: "arn:aws:lambda:#{Jets.aws.region}:#{Jets.aws.account}:function:#{Jets.config.project_namespace}-*",
|
22
|
+
}
|
23
|
+
)
|
10
24
|
|
11
25
|
unless Jets::Commands::Build.poly_only?
|
12
26
|
torching ? rate(PREWARM_RATE) : disable(true)
|
data/lib/jets/lambda/dsl.rb
CHANGED
@@ -76,6 +76,24 @@ module Jets::Lambda::Dsl
|
|
76
76
|
end
|
77
77
|
alias_method :props, :properties
|
78
78
|
|
79
|
+
# definitions: one more many definitions
|
80
|
+
def class_iam_policy(*definitions)
|
81
|
+
if definitions.empty?
|
82
|
+
@class_iam_policy
|
83
|
+
else
|
84
|
+
@class_iam_policy = definitions.flatten
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# definitions: one more many definitions
|
89
|
+
def iam_policy(*definitions)
|
90
|
+
if definitions.empty?
|
91
|
+
@iam_policy
|
92
|
+
else
|
93
|
+
@iam_policy = definitions.flatten
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
79
97
|
# meth is a Symbol
|
80
98
|
def method_added(meth)
|
81
99
|
return if %w[initialize method_missing].include?(meth.to_s)
|
@@ -89,7 +107,7 @@ module Jets::Lambda::Dsl
|
|
89
107
|
# We adjust the class name when we build the functions later in
|
90
108
|
# FunctionContstructor#adjust_tasks.
|
91
109
|
all_tasks[meth] = Jets::Lambda::Task.new(self.name, meth,
|
92
|
-
properties: @properties, lang: lang)
|
110
|
+
properties: @properties, iam_policy: @iam_policy, lang: lang)
|
93
111
|
|
94
112
|
# Done storing options, clear out for the next added method.
|
95
113
|
clear_properties
|
@@ -106,6 +124,7 @@ module Jets::Lambda::Dsl
|
|
106
124
|
|
107
125
|
def clear_properties
|
108
126
|
@properties = nil
|
127
|
+
@iam_policy = nil
|
109
128
|
end
|
110
129
|
|
111
130
|
# Returns the all tasks for this class with their method names as keys.
|
data/lib/jets/lambda/task.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
class Jets::Lambda::Task
|
2
2
|
attr_accessor :class_name, :type
|
3
|
-
attr_reader :meth, :properties, :lang
|
3
|
+
attr_reader :meth, :properties, :iam_policy, :lang
|
4
4
|
def initialize(class_name, meth, options={})
|
5
5
|
@class_name = class_name.to_s # use at EventsRuleMapper#full_task_name
|
6
6
|
@meth = meth
|
7
7
|
@options = options
|
8
8
|
@type = options[:type] || get_type # controller, job, or function
|
9
9
|
@properties = options[:properties] || {}
|
10
|
+
@iam_policy = options[:iam_policy]
|
10
11
|
@lang = options[:lang] || :ruby
|
11
12
|
end
|
12
13
|
|
data/lib/jets/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tung Nguyen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -400,6 +400,7 @@ files:
|
|
400
400
|
- lib/jets.rb
|
401
401
|
- lib/jets/application.rb
|
402
402
|
- lib/jets/application/middleware.rb
|
403
|
+
- lib/jets/aws_info.rb
|
403
404
|
- lib/jets/aws_services.rb
|
404
405
|
- lib/jets/booter.rb
|
405
406
|
- lib/jets/builders.rb
|
@@ -423,6 +424,11 @@ files:
|
|
423
424
|
- lib/jets/cfn/template_builders/function_properties/node_builder.rb
|
424
425
|
- lib/jets/cfn/template_builders/function_properties/python_builder.rb
|
425
426
|
- lib/jets/cfn/template_builders/function_properties/ruby_builder.rb
|
427
|
+
- lib/jets/cfn/template_builders/iam_policy.rb
|
428
|
+
- lib/jets/cfn/template_builders/iam_policy/application_policy.rb
|
429
|
+
- lib/jets/cfn/template_builders/iam_policy/base_policy.rb
|
430
|
+
- lib/jets/cfn/template_builders/iam_policy/class_policy.rb
|
431
|
+
- lib/jets/cfn/template_builders/iam_policy/function_policy.rb
|
426
432
|
- lib/jets/cfn/template_builders/interface.rb
|
427
433
|
- lib/jets/cfn/template_builders/job_builder.rb
|
428
434
|
- lib/jets/cfn/template_builders/parent_builder.rb
|
@@ -438,6 +444,11 @@ files:
|
|
438
444
|
- lib/jets/cfn/template_mappers/function_mapper.rb
|
439
445
|
- lib/jets/cfn/template_mappers/gateway_method_mapper.rb
|
440
446
|
- lib/jets/cfn/template_mappers/gateway_resource_mapper.rb
|
447
|
+
- lib/jets/cfn/template_mappers/iam_policy.rb
|
448
|
+
- lib/jets/cfn/template_mappers/iam_policy/application_policy_mapper.rb
|
449
|
+
- lib/jets/cfn/template_mappers/iam_policy/base_policy_mapper.rb
|
450
|
+
- lib/jets/cfn/template_mappers/iam_policy/class_policy_mapper.rb
|
451
|
+
- lib/jets/cfn/template_mappers/iam_policy/function_policy_mapper.rb
|
441
452
|
- lib/jets/cfn/template_mappers/job_mapper.rb
|
442
453
|
- lib/jets/cfn/template_mappers/lambda_function_mapper.rb
|
443
454
|
- lib/jets/cfn/template_mappers/rule_mapper.rb
|