jets 3.2.1 → 4.0.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.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/jets.gemspec +1 -1
  4. data/lib/jets/application/defaults.rb +2 -0
  5. data/lib/jets/application.rb +6 -7
  6. data/lib/jets/aws_info.rb +2 -2
  7. data/lib/jets/booter.rb +48 -1
  8. data/lib/jets/builders/code_builder.rb +2 -21
  9. data/lib/jets/builders/gem_replacer.rb +2 -7
  10. data/lib/jets/builders/ruby_packager.rb +37 -4
  11. data/lib/jets/cfn/builders/api_deployment_builder.rb +1 -1
  12. data/lib/jets/cfn/builders/api_gateway_builder.rb +25 -22
  13. data/lib/jets/cfn/builders/api_resources_builder.rb +1 -1
  14. data/lib/jets/cfn/builders/authorizer_builder.rb +1 -1
  15. data/lib/jets/cfn/builders/base_child_builder.rb +20 -1
  16. data/lib/jets/cfn/builders/interface.rb +19 -0
  17. data/lib/jets/cfn/builders/parent_builder.rb +3 -3
  18. data/lib/jets/cfn/builders/shared_builder.rb +1 -1
  19. data/lib/jets/cfn/built_template.rb +1 -1
  20. data/lib/jets/cfn/ship.rb +2 -2
  21. data/lib/jets/cfn/status.rb +1 -1
  22. data/lib/jets/cfn/upload.rb +2 -2
  23. data/lib/jets/cli.rb +10 -4
  24. data/lib/jets/commands/call/base_guesser.rb +1 -1
  25. data/lib/jets/commands/clean/log.rb +3 -3
  26. data/lib/jets/commands/configure.rb +1 -1
  27. data/lib/jets/commands/delete.rb +1 -1
  28. data/lib/jets/commands/deploy.rb +2 -2
  29. data/lib/jets/commands/stack_info.rb +1 -1
  30. data/lib/jets/commands/templates/skeleton/config/application.rb.tt +1 -1
  31. data/lib/jets/commands/url.rb +1 -1
  32. data/lib/jets/core.rb +14 -2
  33. data/lib/jets/core_ext/file.rb +9 -0
  34. data/lib/jets/dotenv.rb +2 -2
  35. data/lib/jets/erb.rb +1 -1
  36. data/lib/jets/inflections.rb +1 -1
  37. data/lib/jets/internal/app/controllers/jets/bare_controller.rb +1 -1
  38. data/lib/jets/internal/app/functions/jets/base_path.rb +93 -3
  39. data/lib/jets/internal/app/functions/jets/base_path_mapping.rb +65 -6
  40. data/lib/jets/internal/app/jobs/jets/preheat_job.rb +6 -2
  41. data/lib/jets/lambda/dsl.rb +6 -1
  42. data/lib/jets/{naming.rb → names.rb} +3 -3
  43. data/lib/jets/preheat.rb +9 -6
  44. data/lib/jets/resource/api_gateway/base_path/role.rb +1 -1
  45. data/lib/jets/resource/api_gateway/deployment.rb +2 -2
  46. data/lib/jets/resource/api_gateway/rest_api/logical_id.rb +1 -1
  47. data/lib/jets/resource/api_gateway/rest_api/routes/change/base.rb +1 -1
  48. data/lib/jets/resource/api_gateway/rest_api/routes/change/media_types.rb +1 -1
  49. data/lib/jets/resource/api_gateway/rest_api/routes/change/page.rb +2 -2
  50. data/lib/jets/resource/api_gateway/rest_api/routes/change.rb +1 -1
  51. data/lib/jets/resource/api_gateway/rest_api.rb +1 -1
  52. data/lib/jets/resource/child_stack/api_deployment.rb +1 -1
  53. data/lib/jets/resource/child_stack/api_resource/page.rb +1 -1
  54. data/lib/jets/resource/child_stack/api_resource.rb +1 -1
  55. data/lib/jets/resource/child_stack/app_class.rb +1 -1
  56. data/lib/jets/resource/child_stack/shared.rb +1 -1
  57. data/lib/jets/resource/iam/base_role_definition.rb +0 -5
  58. data/lib/jets/resource/iam/policy.rb +31 -0
  59. data/lib/jets/resource/lambda/function/environment.rb +2 -1
  60. data/lib/jets/resource/lambda/function.rb +3 -3
  61. data/lib/jets/router/route.rb +16 -4
  62. data/lib/jets/tmp_loader.rb +1 -1
  63. data/lib/jets/turbo/database_yaml.rb +1 -1
  64. data/lib/jets/util/yamler.rb +16 -0
  65. data/lib/jets/version.rb +1 -1
  66. data/lib/jets.rb +1 -0
  67. metadata +7 -9
  68. data/.python-version +0 -1
  69. data/.ruby-version +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8fedba281ee9d6ac31a44184b49bbc8fe15d309a3f4d58142cfa25c4ddebc153
4
- data.tar.gz: e73ee950202ea1786c881b43abc95c03bc4c3e7ef44b04265997eca2f4b9211b
3
+ metadata.gz: 557e01dec1b92f8a04213ef4b7f5ee9d8a35f25dd20231c96ba24b0d9890b7cd
4
+ data.tar.gz: 5c8c12ae959d76dc9e5a681c8f18a40d5d60defcc4eead52ed9d9ad2571a3fe1
5
5
  SHA512:
6
- metadata.gz: 57070368542b8a767fbf8553f0c627b36432e691ae07f1f41488a0d8af830bffd1ed84a71633fe971df6b45bcf79ff8862f2d4513d22e4a1981b633f36cbb8bd
7
- data.tar.gz: 32ba83eb4d4e87a8c92b5d7ec8d573ae2b36ff558fedbae7bb33f1ebe5dbcb36baf2f64b89b2a05d2e56e52bcd2145964a0770f7a56efdb48d1a925498c7f177
6
+ metadata.gz: 944a1d09ba4da26110e292cdf42d73a240d283d066dbe1ca677787c20b03ee925cf12e3d92555bc16e6327c7096ce59782cd271ff802f5d8554819674f040020
7
+ data.tar.gz: 987eac8ef96a9cc10b0ac071ff099c02245cf5143bb75d23622513aba73ba447414ab0c542f7a734c30ba6ce07f20cd479daecc030c02d9a5d3505c10c0a5c34
data/CHANGELOG.md CHANGED
@@ -3,6 +3,27 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  This project *loosely tries* to adhere to [Semantic Versioning](http://semver.org/).
5
5
 
6
+ ## [4.0.0] - 2023-05-27
7
+ - [#641](https://github.com/boltops-tools/jets/pull/641) bundle check and prevent error from getting to aws lambda
8
+ - [#642](https://github.com/boltops-tools/jets/pull/642) Fix rack mounted apps: update interface with removed meth
9
+ - [#643](https://github.com/boltops-tools/jets/pull/643) JETS_EXTRA support, deprecate JETS_ENV_EXTRA
10
+ - [#644](https://github.com/boltops-tools/jets/pull/644) remove docs to separate repo
11
+ - [#645](https://github.com/boltops-tools/jets/pull/645) PreheatJob: fix function lookups and iam function permission
12
+ - [#646](https://github.com/boltops-tools/jets/pull/646) log debug uploading and setting content type
13
+ - [#647](https://github.com/boltops-tools/jets/pull/647) fix Jets.logger call
14
+ - [#648](https://github.com/boltops-tools/jets/pull/648) make sure logger level info is default
15
+ - [#649](https://github.com/boltops-tools/jets/pull/649) Custom Domain: Hard fail on IAM permission error
16
+ - [#650](https://github.com/boltops-tools/jets/pull/650) Validate lambda function names
17
+ - [#651](https://github.com/boltops-tools/jets/pull/651) allow custom rake tasks with params to work with jets as well as rake command
18
+ - [#652](https://github.com/boltops-tools/jets/pull/652) Validate lambda function names: fix regexp
19
+ - [#653](https://github.com/boltops-tools/jets/pull/653) refactor cleanup: rename Jets::Naming to Jets::Names
20
+ - [#654](https://github.com/boltops-tools/jets/pull/654) Ruby 3.2 Support
21
+ - apigw routes state save: fix to_json infinite loop from Grape apps
22
+ - delete .python-version: more general approach. fixes specs when specific version of python is not installed
23
+
24
+ ## [3.2.2] - 2023-05-19
25
+ - [#640](https://github.com/boltops-tools/jets/pull/640) Base path mapping CloudFormation custom resource and lambda function hardening
26
+
6
27
  ## [3.2.1] - 2023-05-03
7
28
  - [#637](https://github.com/boltops-tools/jets/pull/637) Readme: Replace "splat out" with "had" a baby
8
29
  - [#638](https://github.com/boltops-tools/jets/pull/638) feature: update an array of reserved variables in aws lambda
data/jets.gemspec CHANGED
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = "https://rubyonjets.com"
15
15
  spec.license = "MIT"
16
16
 
17
- spec.required_ruby_version = ['>= 2.5.0', '< 3.0.0']
17
+ spec.required_ruby_version = ['>= 2.5.0']
18
18
  spec.rdoc_options += Jets::Rdoc.options
19
19
 
20
20
  vendor_files = Dir.glob("vendor/**/*")
@@ -51,6 +51,7 @@ class Jets::Application
51
51
  config.autoload_paths = [] # allows for customization
52
52
  config.ignore_paths = [] # allows for customization
53
53
  config.logger = Jets::Logger.new($stderr)
54
+ config.logger.level = Logger::INFO
54
55
  config.time_zone = "UTC"
55
56
 
56
57
  # function properties defaults
@@ -162,6 +163,7 @@ class Jets::Application
162
163
 
163
164
  config.ruby = ActiveSupport::OrderedOptions.new
164
165
  config.ruby.check = true
166
+ config.ruby.supported_versions = %w[2.5 2.7 3.2] # supported by AWS Lambda
165
167
 
166
168
  config
167
169
  end
@@ -163,13 +163,12 @@ class Jets::Application
163
163
  staging: 'stag',
164
164
  }
165
165
  def set_computed_configs!
166
- # env_extra can be also be set with JETS_ENV_EXTRA.
167
- # JETS_ENV_EXTRA higher precedence than config.env_extra
168
- config.env_extra = ENV['JETS_ENV_EXTRA'] if ENV['JETS_ENV_EXTRA']
169
- # IE: With env_extra: project-dev-1
170
- # Without env_extra: project-dev
166
+ # env var JETS_EXTRA higher precedence than config.extra
167
+ config.extra = Jets.extra
168
+ # IE: With extra: project-dev-1
169
+ # Without extra: project-dev
171
170
  config.short_env = ENV_MAP[Jets.env.to_sym] || Jets.env
172
- # table_namespace does not have the env_extra, more common case desired.
171
+ # table_namespace does not have the extra, more common case desired.
173
172
  config.table_namespace = [config.project_name, config.short_env].compact.join('-')
174
173
 
175
174
  config.project_namespace = Jets.project_namespace
@@ -205,7 +204,7 @@ class Jets::Application
205
204
  if File.exist?(database_yml)
206
205
  require "active_record/database_configurations" # lazy require
207
206
  text = Jets::Erb.result(database_yml)
208
- db_configs = YAML.load(text)
207
+ db_configs = Jets::Util::Yamler.load(text)
209
208
  configurations = ActiveRecord::DatabaseConfigurations.new(db_configs)
210
209
  config.database = configurations
211
210
  end
data/lib/jets/aws_info.rb CHANGED
@@ -73,7 +73,7 @@ module Jets
73
73
  return "fake-test-s3-bucket" if Jets.env.test?
74
74
  return @@s3_bucket unless @@s3_bucket == BUCKET_DOES_NOT_YET_EXIST
75
75
 
76
- resp = cfn.describe_stacks(stack_name: Jets::Naming.parent_stack_name)
76
+ resp = cfn.describe_stacks(stack_name: Jets::Names.parent_stack_name)
77
77
  stack = resp.stacks.first
78
78
  output = stack["outputs"].find { |o| o["output_key"] == "S3Bucket" }
79
79
  @@s3_bucket = output["output_value"] # s3_bucket
@@ -83,7 +83,7 @@ module Jets
83
83
  # not been loaded in the config yet. We do some trickery with loading
84
84
  # the config twice in Application#load_app_config
85
85
  # The first load will result in a Aws::CloudFormation::Errors::ValidationError
86
- # since the Jets::Naming.parent_stack_name has not been properly set yet.
86
+ # since the Jets::Names.parent_stack_name has not been properly set yet.
87
87
  #
88
88
  # Rescuing all exceptions in case there are other exceptions dont know about yet
89
89
  # Here are the known ones: Aws::CloudFormation::Errors::ValidationError, Aws::CloudFormation::Errors::InvalidClientTokenId
data/lib/jets/booter.rb CHANGED
@@ -10,6 +10,7 @@ class Jets::Booter
10
10
  Jets::Bundle.require
11
11
 
12
12
  Jets.application.setup!
13
+ check_ruby_version!
13
14
 
14
15
  # Turbines are loaded after setup_autoload_paths in Jets.application.setup! Some Turbine options are defined
15
16
  # in the project so setup must happen before internal Turbines are loaded.
@@ -98,7 +99,7 @@ class Jets::Booter
98
99
  primary_hash_config = ActiveRecord::Base.configurations.configs_for(env_name: Jets.env).find { |hash_config|
99
100
  hash_config.name == "primary"
100
101
  }
101
-
102
+
102
103
  primary_config = primary_hash_config.configuration_hash # configuration_hash is a normal Ruby Hash
103
104
 
104
105
  ActiveRecord::Base.establish_connection(primary_config)
@@ -174,5 +175,51 @@ class Jets::Booter
174
175
  exit 1
175
176
  end
176
177
  end
178
+
179
+ def check_ruby_version!
180
+ return if ENV['JETS_RUBY_CHECK'] == '0'
181
+ return if !Jets.config.ruby.check
182
+ return if ruby_version_supported?
183
+
184
+ puts <<~EOL.color(:red)
185
+ You are using Ruby #{RUBY_VERSION}
186
+ AWS Lambda does not support this version.
187
+ Please use one of the supported Ruby versions: #{supported_ruby_versions.join(' ')}
188
+ EOL
189
+
190
+ puts <<~EOL
191
+ If you would like to skip this check, you can set: JETS_RUBY_CHECK=0 or configure
192
+
193
+ config/application.rb
194
+
195
+ Jets.application.configure do
196
+ config.ruby.check = false
197
+ end
198
+
199
+ Or if you want to allow additional Ruby versions, then configure:
200
+
201
+ config/application.rb
202
+
203
+ Jets.application.configure do
204
+ config.ruby.supported_versions = ["2.5", "2.7", "3.2"]
205
+ end
206
+
207
+ Note: If AWS Lambda does not officially support the Ruby version,
208
+ you'll need to also provide the Ruby Custom Runtime Layer.
209
+ Related Docs: https://rubyonjets.com/docs/extras/custom-runtime/
210
+ EOL
211
+ exit 1
212
+ end
213
+
214
+ def ruby_version_supported?
215
+ md = RUBY_VERSION.match(/(\d+)\.(\d+)\.\d+/)
216
+ major, minor = md[1], md[2]
217
+ detected_ruby = [major, minor].join('.')
218
+ supported_ruby_versions.include?(detected_ruby)
219
+ end
220
+
221
+ def supported_ruby_versions
222
+ Jets.config.ruby.supported_versions
223
+ end
177
224
  end
178
225
  end
@@ -26,7 +26,6 @@ module Jets::Builders
26
26
  end
27
27
 
28
28
  def build
29
- check_ruby_version
30
29
  @version_purger.purge
31
30
  cache_check_message
32
31
 
@@ -80,6 +79,7 @@ module Jets::Builders
80
79
  return false if ENV['JETS_BUILD_NO_INTERNET']
81
80
  s3_key = "jets/code/#{filename}"
82
81
  begin
82
+ Jets.logger.debug "Checking s3://#{s3_bucket}/#{s3_key}"
83
83
  s3.head_object(bucket: s3_bucket, key: s3_key)
84
84
  true
85
85
  rescue Aws::S3::Errors::NotFound, Aws::S3::Errors::Forbidden
@@ -355,7 +355,7 @@ module Jets::Builders
355
355
  webpacker_yml = "#{"#{stage_area}/code"}/config/webpacker.yml"
356
356
  return unless File.exist?(webpacker_yml)
357
357
 
358
- config = YAML.load_file(webpacker_yml)
358
+ config = Jets::Util::Yamler.load_file(webpacker_yml)
359
359
  config["development"]["compile"] = false # force this to be false for deployment
360
360
  new_yaml = YAML.dump(config)
361
361
  IO.write(webpacker_yml, new_yaml)
@@ -412,25 +412,6 @@ module Jets::Builders
412
412
  FileUtils.cp_r(ruby_version_path, build_area)
413
413
  end
414
414
 
415
- SUPPORTED_RUBY_VERSIONS = %w[2.5 2.7]
416
- def check_ruby_version
417
- return unless ENV['JETS_RUBY_CHECK'] == '0' || Jets.config.ruby.check == false
418
- return if ruby_version_supported?
419
- puts <<~EOL.color(:red)
420
- You are using Ruby version #{RUBY_VERSION} which is not supported by Jets.
421
- Please use one of the Jets supported ruby versions: #{SUPPORTED_RUBY_VERSIONS.join(' ')}
422
- If you would like to skip this check you can set: JETS_RUBY_CHECK=0
423
- EOL
424
- exit 1
425
- end
426
-
427
- def ruby_version_supported?
428
- md = RUBY_VERSION.match(/(\d+)\.(\d+)\.\d+/)
429
- major, minor = md[1], md[2]
430
- detected_ruby = [major, minor].join('.')
431
- SUPPORTED_RUBY_VERSIONS.include?(detected_ruby)
432
- end
433
-
434
415
  # Group all the path settings together here
435
416
  def self.tmp_code
436
417
  Jets::Commands::Build.tmp_code
@@ -1,6 +1,8 @@
1
1
  module Jets::Builders
2
2
  class GemReplacer
3
3
  extend Memoist
4
+ include Util
5
+
4
6
  def initialize(options)
5
7
  @options = options
6
8
  end
@@ -37,13 +39,6 @@ module Jets::Builders
37
39
  FileUtils.mv(src, dest) unless File.exist?(dest) # looks like rename_gem actually runs twice
38
40
  end
39
41
 
40
- def sh(command)
41
- puts "=> #{command}".color(:green)
42
- success = system(command)
43
- abort("Command Failed: #{command}") unless success
44
- success
45
- end
46
-
47
42
  def ruby_folder
48
43
  Jets::Gems.ruby_folder
49
44
  end
@@ -3,9 +3,9 @@ require "bundler" # for clean_old_submodules only
3
3
  module Jets::Builders
4
4
  class RubyPackager
5
5
  include Util
6
-
7
- GEM_REGEXP = /-(arm|x)\d+.*-(darwin|linux)/
8
-
6
+
7
+ GEM_REGEXP = /-(arm|x)\d+.*-(darwin|linux)/
8
+
9
9
  attr_reader :full_app_root
10
10
  def initialize(relative_app_root)
11
11
  @full_app_root = "#{build_area}/#{relative_app_root}"
@@ -16,6 +16,7 @@ module Jets::Builders
16
16
 
17
17
  clean_old_submodules
18
18
  bundle_install
19
+ bundle_check
19
20
  copy_bundle_config
20
21
  copy_cache_gems
21
22
  end
@@ -75,7 +76,39 @@ module Jets::Builders
75
76
  # For example we add the jets-rails to the Gemfile.
76
77
  copy_back_gemfile_lock
77
78
 
78
- puts 'Bundle install success.'
79
+ puts 'Bundle install completed'
80
+ end
81
+
82
+ # Example `bundle check` error:
83
+ #
84
+ # The following gems are missing
85
+ # * date (3.3.3)
86
+ # * timeout (0.3.2)
87
+ # Install missing gems with `bundle install`
88
+ #
89
+ # Example success:
90
+ #
91
+ # The Gemfile's dependencies are satisfied
92
+ #
93
+ def bundle_check
94
+ out = ''
95
+ Bundler.with_unbundled_env do
96
+ out = `cd #{cache_area} && bundle check 2>&1`
97
+ end
98
+ if out.include?("missing")
99
+ puts "Failed: bundle check".color(:red)
100
+ puts <<~EOL
101
+ This means something went wrong with the bundle install.
102
+ Jets will prevent the deployment to AWS Lambda.
103
+ It's better to error now instead of finding out on AWS Lambda.
104
+ The bundle install can fail for different system-specific reasons.
105
+ It could be an outdated or incompatible version of RubyGems and Ruby.
106
+
107
+ Related: https://community.boltops.com/t/could-not-find-timeout-0-3-1-in-any-of-the-sources/996
108
+
109
+ EOL
110
+ exit 1
111
+ end
79
112
  end
80
113
 
81
114
  def copy_back_gemfile_lock
@@ -45,7 +45,7 @@ module Jets::Cfn::Builders
45
45
 
46
46
  # template_path is an interface method
47
47
  def template_path
48
- Jets::Naming.api_deployment_template_path
48
+ Jets::Names.api_deployment_template_path
49
49
  end
50
50
 
51
51
  # do not bother writing a template if routes are empty
@@ -18,7 +18,7 @@ module Jets::Cfn::Builders
18
18
 
19
19
  # template_path is an interface method
20
20
  def template_path
21
- Jets::Naming.api_gateway_template_path
21
+ Jets::Names.api_gateway_template_path
22
22
  end
23
23
 
24
24
  # do not bother writing a template if routes are empty
@@ -55,7 +55,7 @@ module Jets::Cfn::Builders
55
55
  end
56
56
  end
57
57
 
58
- def create_domain_name()
58
+ def create_domain_name
59
59
  resource = Jets::Resource::ApiGateway::DomainName.new
60
60
 
61
61
  return {
@@ -70,41 +70,44 @@ module Jets::Cfn::Builders
70
70
  apigateway.get_domain_name({
71
71
  domain_name: resource.domain_name
72
72
  })
73
- return true
74
- rescue
75
- return false
73
+ true
74
+ # IE: Aws::APIGateway::Errors::NotFoundException Invalid domain name identifier specified
75
+ rescue Aws::APIGateway::Errors::NotFoundException
76
+ false
76
77
  end
77
78
  memoize :existing_domain_name?
78
79
 
79
80
  def existing_domain_name_on_stack?
80
- cfn.describe_stack_resource({
81
+ cfn.describe_stack_resource(
81
82
  stack_name: api_gateway_physical_resource_id,
82
83
  logical_resource_id: "DomainName"
83
- })
84
- return true
85
- rescue
86
- return false
84
+ )
85
+ true
86
+ # IE: Aws::CloudFormation::Errors::ValidationError (Resource DomainName does not exist for stack demo-dev)
87
+ rescue Aws::CloudFormation::Errors::ValidationError
88
+ false
87
89
  end
88
90
 
89
91
  def existing_dns_record_on_stack?
90
- cfn.describe_stack_resource({
92
+ cfn.describe_stack_resource(
91
93
  stack_name: api_gateway_physical_resource_id,
92
94
  logical_resource_id: "DnsRecord"
93
- })
94
- return true
95
- rescue
96
- return false
95
+ )
96
+ true
97
+ # IE: Aws::CloudFormation::Errors::ValidationError (Resource DnsRecord does not exist for stack demo-dev)
98
+ rescue Aws::CloudFormation::Errors::ValidationError
99
+ false
97
100
  end
98
101
 
99
102
  def api_gateway_physical_resource_id
100
- cfn.describe_stack_resource({
101
- stack_name: Jets::Naming.parent_stack_name,
103
+ resp = cfn.describe_stack_resource(
104
+ stack_name: Jets::Names.parent_stack_name,
102
105
  logical_resource_id: "ApiGateway"
103
- })
104
- .stack_resource_detail
105
- .physical_resource_id
106
- rescue
107
- return nil
106
+ )
107
+ resp&.stack_resource_detail&.physical_resource_id
108
+ # IE: Aws::CloudFormation::Errors::ValidationError (Resource ApiGateway does not exist for stack demo-dev)
109
+ rescue Aws::CloudFormation::Errors::ValidationError
110
+ nil
108
111
  end
109
112
  memoize :api_gateway_physical_resource_id
110
113
 
@@ -16,7 +16,7 @@ module Jets::Cfn::Builders
16
16
 
17
17
  # template_path is an interface method
18
18
  def template_path
19
- Jets::Naming.api_resources_template_path(@page)
19
+ Jets::Names.api_resources_template_path(@page)
20
20
  end
21
21
 
22
22
  def add_rest_api_parameter
@@ -61,7 +61,7 @@ module Jets::Cfn::Builders
61
61
  end
62
62
 
63
63
  def template_path
64
- Jets::Naming.authorizer_template_path(@path)
64
+ Jets::Names.authorizer_template_path(@path)
65
65
  end
66
66
  end
67
67
  end
@@ -18,7 +18,7 @@ module Jets::Cfn::Builders
18
18
 
19
19
  # template_path is an interface method for Interface module
20
20
  def template_path
21
- Jets::Naming.app_template_path(@app_class)
21
+ Jets::Names.app_template_path(@app_class)
22
22
  end
23
23
 
24
24
  def add_common_parameters
@@ -40,6 +40,7 @@ module Jets::Cfn::Builders
40
40
  end
41
41
 
42
42
  def add_functions
43
+ validate_function_names!
43
44
  add_class_iam_policy
44
45
  @app_class.tasks.each do |task|
45
46
  add_function(task)
@@ -65,5 +66,23 @@ module Jets::Cfn::Builders
65
66
  resource = Jets::Resource::Iam::FunctionRole.new(task)
66
67
  add_resource(resource)
67
68
  end
69
+
70
+ def validate_function_names!
71
+ invalids = @app_class.tasks.reject do |task|
72
+ task.meth.to_s =~ /^[a-zA-Z][a-zA-Z0-9_]/
73
+ end
74
+ return if invalids.empty?
75
+ list = invalids.map do |task|
76
+ " #{task.class_name}##{task.meth}" # IE: PostsController#index
77
+ end.join("\n")
78
+ puts "ERROR: Detected invalid AWS Lambda function names".color(:red)
79
+ puts <<~EOL
80
+ Lambda function names must start with a letter and can only contain letters, numbers, and underscores.
81
+ Invalid function names:
82
+
83
+ #{list}
84
+ EOL
85
+ exit 1
86
+ end
68
87
  end
69
88
  end
@@ -88,8 +88,27 @@ module Jets::Cfn::Builders
88
88
  end
89
89
  end
90
90
 
91
+ # Note: Jets::Resource::Iam classes are special treated. They are the only resources that result
92
+ # in creating 2 CloudFormation resources: Iam::Policy and Iam::Role.
93
+ # This allows the user to refer to the Lambda Function name in the IAM Policy itself.
94
+ # We need separate resources to avoid CloudFormation erroring with a circular dependency.
95
+ # Using separate IAM::Policy and IAM::Role resources allows us avoid the circular dependency error.
96
+ #
97
+ # Handling logic here also centralizes code for this special behavior.
98
+ # Also important to note, this does not change the user-facing interface.
99
+ # IE: Users still uses code like:
100
+ #
101
+ # iam_policy("s3", "sns")
102
+ #
103
+ # and be none-the-wiser about the special behavior.
91
104
  def add_resource(resource)
92
105
  add_template_resource(resource.logical_id, resource.type, resource.attributes)
106
+
107
+ if resource.class.to_s.include?("Jets::Resource::Iam")
108
+ role = resource # for clarity: resource is a Iam::*Role class
109
+ iam_policy = Jets::Resource::Iam::Policy.new(role)
110
+ add_template_resource(iam_policy.logical_id, iam_policy.type, iam_policy.attributes)
111
+ end
93
112
  end
94
113
 
95
114
  # The add_resource method can take an options Hash with both with either
@@ -19,7 +19,7 @@ module Jets::Cfn::Builders
19
19
 
20
20
  # template_path is an interface method
21
21
  def template_path
22
- Jets::Naming.parent_template_path
22
+ Jets::Names.parent_template_path
23
23
  end
24
24
 
25
25
  def build_minimal_resources
@@ -90,7 +90,7 @@ module Jets::Cfn::Builders
90
90
  # #{Jets.build_root}/templates/demo-dev-2-app-comments_controller.yml
91
91
  # #{Jets.build_root}/templates/demo-dev-2-authorizers-main_authorizer.yml
92
92
  def for_each_path(type)
93
- expression = "#{Jets::Naming.template_path_prefix}-#{type}-*"
93
+ expression = "#{Jets::Names.template_path_prefix}-#{type}-*"
94
94
  Dir.glob(expression).each do |path|
95
95
  next unless File.file?(path)
96
96
  yield(path)
@@ -123,7 +123,7 @@ module Jets::Cfn::Builders
123
123
  end
124
124
 
125
125
  def add_api_resources
126
- expression = "#{Jets::Naming.template_path_prefix}-api-resources-*"
126
+ expression = "#{Jets::Names.template_path_prefix}-api-resources-*"
127
127
  # IE: path: #{Jets.build_root}/templates/demo-dev-2-api-resources-1.yml"
128
128
  Dir.glob(expression).sort.each do |path|
129
129
  next unless File.file?(path)
@@ -8,7 +8,7 @@ module Jets::Cfn::Builders
8
8
 
9
9
  # template_path is an interface method for Interface module
10
10
  def template_path
11
- Jets::Naming.shared_template_path(@app_class)
11
+ Jets::Names.shared_template_path(@app_class)
12
12
  end
13
13
  end
14
14
  end
@@ -7,7 +7,7 @@ module Jets::Cfn
7
7
  if @@cache[path]
8
8
  @@cache[path] # using cache
9
9
  else
10
- @@cache[path] = YAML.load_file(path) # setting and using cache
10
+ @@cache[path] = Jets::Util::Yamler.load_file(path) # setting and using cache
11
11
  end
12
12
  end
13
13
  end
data/lib/jets/cfn/ship.rb CHANGED
@@ -5,7 +5,7 @@ module Jets::Cfn
5
5
 
6
6
  def initialize(options)
7
7
  @options = options
8
- @parent_stack_name = Jets::Naming.parent_stack_name
8
+ @parent_stack_name = Jets::Names.parent_stack_name
9
9
  end
10
10
 
11
11
  def run
@@ -81,7 +81,7 @@ module Jets::Cfn
81
81
  end
82
82
 
83
83
  def template
84
- @template ||= TemplateSource.new(Jets::Naming.parent_template_path, @options)
84
+ @template ||= TemplateSource.new(Jets::Names.parent_template_path, @options)
85
85
  end
86
86
 
87
87
  # check for /(_COMPLETE|_FAILED)$/ status
@@ -3,7 +3,7 @@ require 'cfn_status'
3
3
  module Jets::Cfn
4
4
  class Status < CfnStatus
5
5
  def initialize(options={})
6
- @stack_name = Jets::Naming.parent_stack_name
6
+ @stack_name = Jets::Names.parent_stack_name
7
7
  super(@stack_name, options)
8
8
  end
9
9
  end
@@ -21,7 +21,7 @@ module Jets::Cfn
21
21
 
22
22
  def upload_cfn_templates
23
23
  puts "Uploading CloudFormation templates to S3."
24
- expression = "#{Jets::Naming.template_path_prefix}-*"
24
+ expression = "#{Jets::Names.template_path_prefix}-*"
25
25
  Dir.glob(expression).each do |path|
26
26
  next unless File.file?(path)
27
27
 
@@ -93,7 +93,7 @@ module Jets::Cfn
93
93
  key = s3_key(full_path)
94
94
  obj = s3_resource.bucket(bucket_name).object(key)
95
95
  content_type = content_type_headers(full_path)
96
- puts "Uploading and setting content type for s3://#{bucket_name}/#{key} content_type #{content_type[:content_type].inspect}"
96
+ Jets.logger.debug "Uploading and setting content type for s3://#{bucket_name}/#{key} content_type #{content_type[:content_type].inspect}"
97
97
  obj.upload_file(full_path, { acl: "public-read", cache_control: cache_control }.merge(content_type))
98
98
  end
99
99
 
data/lib/jets/cli.rb CHANGED
@@ -137,10 +137,16 @@ class Jets::CLI
137
137
  end
138
138
 
139
139
  return unless jets_project?
140
- rake_task_found = Jets::Commands::RakeCommand.namespaced_commands.include?(full_command)
141
- if rake_task_found
142
- return Jets::Commands::RakeCommand
143
- end
140
+
141
+ Jets::Commands::RakeCommand if rake_task_found
142
+ end
143
+
144
+ def rake_task_found
145
+ return false unless full_command # can be nil for subcommands and would break jets help without this check
146
+ bracket_regex = /\[.*/ # matches everything after the first [
147
+ command = full_command.sub(bracket_regex, '') # remove everything after the first [
148
+ namespaced_commands = Jets::Commands::RakeCommand.namespaced_commands.map {|x| x.sub(bracket_regex, '') }
149
+ namespaced_commands.include?(command)
144
150
  end
145
151
 
146
152
  def jets_project?
@@ -56,7 +56,7 @@ class Jets::Commands::Call
56
56
 
57
57
  @@parent_stack = nil
58
58
  def parent_stack
59
- @@parent_stack ||= cfn.describe_stacks(stack_name: Jets::Naming.parent_stack_name).stacks.first
59
+ @@parent_stack ||= cfn.describe_stacks(stack_name: Jets::Names.parent_stack_name).stacks.first
60
60
  end
61
61
  end
62
62
  end
@@ -4,7 +4,7 @@
4
4
  # /aws/lambda/demo-dev-2-jets-preheat_job-warm
5
5
  # /aws/lambda/demo-dev-2-jets-public_controller-show
6
6
  #
7
- # We're doing this because JETS_ENV_EXTRA environments can create additional matching
7
+ # We're doing this because Jets.extra environments can create additional matching
8
8
  # log groups and we don't want to overly-aggressively delete them.
9
9
  #
10
10
  # The `keep_prefixes(log_group_names)` method calcuates the log groups to keep.
@@ -49,7 +49,7 @@ class Jets::Commands::Clean
49
49
 
50
50
  private
51
51
  def prefix_guess
52
- Jets::Naming.parent_stack_name
52
+ Jets::Names.parent_stack_name
53
53
  end
54
54
 
55
55
  def log_groups
@@ -78,7 +78,7 @@ class Jets::Commands::Clean
78
78
 
79
79
  # Check for the prefixes to keep. The slightly tricky thing to watch for is
80
80
  # for the prefix matching addiitonal log groups that belong to other
81
- # JETS_ENV_EXTRA=xxx created environments.
81
+ # JETS_EXTRA=xxx created environments.
82
82
  #
83
83
  # We find and store the prefixes to keep so we don't over aggressively delete
84
84
  # log groups.