jets 2.3.17 → 3.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +0 -3
  3. data/.python-version +1 -1
  4. data/.ruby-version +1 -1
  5. data/CHANGELOG.md +44 -0
  6. data/LICENSE.txt +1 -1
  7. data/README.md +5 -3
  8. data/backers.md +2 -0
  9. data/jets.gemspec +12 -10
  10. data/lib/jets.rb +9 -13
  11. data/lib/jets/application.rb +9 -2
  12. data/lib/jets/application/defaults.rb +17 -15
  13. data/lib/jets/autoloaders.rb +15 -1
  14. data/lib/jets/booter.rb +3 -3
  15. data/lib/jets/builders/code_builder.rb +16 -15
  16. data/lib/jets/builders/gem_replacer.rb +15 -4
  17. data/lib/jets/builders/lambda_layer.rb +4 -5
  18. data/lib/jets/builders/ruby_packager.rb +40 -20
  19. data/lib/jets/builders/tidy.rb +1 -2
  20. data/lib/jets/bundle.rb +6 -0
  21. data/lib/jets/cfn/builders/api_gateway_builder.rb +61 -7
  22. data/lib/jets/cfn/ship.rb +2 -1
  23. data/lib/jets/cfn/upload.rb +18 -2
  24. data/lib/jets/cli.rb +6 -1
  25. data/lib/jets/commands/base.rb +1 -1
  26. data/lib/jets/commands/call.rb +14 -1
  27. data/lib/jets/commands/clean.rb +1 -1
  28. data/lib/jets/commands/clean/base.rb +1 -1
  29. data/lib/jets/commands/configure.rb +51 -0
  30. data/lib/jets/commands/delete.rb +2 -2
  31. data/lib/jets/commands/gems.rb +2 -10
  32. data/lib/jets/commands/help/call.md +8 -0
  33. data/lib/jets/commands/help/gems/check.md +3 -5
  34. data/lib/jets/commands/main.rb +9 -1
  35. data/lib/jets/commands/new.rb +9 -1
  36. data/lib/jets/commands/sequence.rb +6 -0
  37. data/lib/jets/commands/templates/skeleton/Gemfile.tt +1 -1
  38. data/lib/jets/commands/templates/skeleton/config/application.rb.tt +1 -1
  39. data/lib/jets/commands/templates/skeleton/public/index.html.tt +1 -1
  40. data/lib/jets/commands/url.rb +1 -0
  41. data/lib/jets/controller/base.rb +14 -4
  42. data/lib/jets/controller/middleware/main.rb +2 -1
  43. data/lib/jets/controller/params.rb +26 -4
  44. data/lib/jets/controller/rack/env.rb +18 -1
  45. data/lib/jets/controller/rendering.rb +5 -2
  46. data/lib/jets/controller/rendering/rack_renderer.rb +7 -1
  47. data/lib/jets/core.rb +12 -4
  48. data/lib/jets/dotenv/ssm.rb +18 -4
  49. data/lib/jets/generator.rb +2 -3
  50. data/lib/jets/internal/app/controllers/jets/public_controller.rb +2 -2
  51. data/lib/jets/internal/app/functions/jets/base_path.rb +10 -149
  52. data/lib/jets/internal/app/functions/jets/base_path_mapping.rb +81 -0
  53. data/lib/jets/internal/app/shared/functions/jets/s3_bucket_config.rb +14 -24
  54. data/lib/jets/resource/api_gateway/base_path/function.rb +6 -1
  55. data/lib/jets/resource/api_gateway/deployment.rb +2 -0
  56. data/lib/jets/resource/api_gateway/method.rb +1 -1
  57. data/lib/jets/resource/api_gateway/resource.rb +1 -1
  58. data/lib/jets/resource/api_gateway/rest_api/logical_id.rb +34 -0
  59. data/lib/jets/resource/api_gateway/rest_api/logical_id/message.rb +49 -0
  60. data/lib/jets/resource/child_stack/api_deployment.rb +2 -0
  61. data/lib/jets/resource/lambda/function.rb +1 -1
  62. data/lib/jets/router/dsl.rb +7 -1
  63. data/lib/jets/router/method_creator/code.rb +1 -1
  64. data/lib/jets/router/scope.rb +7 -3
  65. data/lib/jets/spec_helpers/controllers.rb +10 -3
  66. data/lib/jets/spec_helpers/controllers/request.rb +12 -5
  67. data/lib/jets/stack/main/dsl/lambda.rb +1 -1
  68. data/lib/jets/turbo.rb +1 -0
  69. data/lib/jets/version.rb +1 -1
  70. metadata +63 -56
  71. data/vendor/cfn-status/CHANGELOG.md +0 -14
  72. data/vendor/cfn-status/Gemfile +0 -4
  73. data/vendor/cfn-status/LICENSE.txt +0 -21
  74. data/vendor/cfn-status/README.md +0 -56
  75. data/vendor/cfn-status/Rakefile +0 -6
  76. data/vendor/cfn-status/bin/console +0 -14
  77. data/vendor/cfn-status/bin/setup +0 -8
  78. data/vendor/cfn-status/cfn-status.gemspec +0 -30
  79. data/vendor/cfn-status/lib/cfn-status.rb +0 -1
  80. data/vendor/cfn-status/lib/cfn_status.rb +0 -245
  81. data/vendor/cfn-status/lib/cfn_status/aws_service.rb +0 -51
  82. data/vendor/cfn-status/lib/cfn_status/version.rb +0 -3
  83. data/vendor/cfn-status/spec/fixtures/cfn/pages/fresh/describe_stack_events-1.json +0 -1103
  84. data/vendor/cfn-status/spec/fixtures/cfn/pages/fresh/describe_stack_events-2.json +0 -1104
  85. data/vendor/cfn-status/spec/fixtures/cfn/pages/fresh/describe_stack_events-3.json +0 -1103
  86. data/vendor/cfn-status/spec/fixtures/cfn/pages/updating/describe_stack_events-1.json +0 -1103
  87. data/vendor/cfn-status/spec/fixtures/cfn/pages/updating/describe_stack_events-2.json +0 -1104
  88. data/vendor/cfn-status/spec/fixtures/cfn/pages/updating/describe_stack_events-3.json +0 -1103
  89. data/vendor/cfn-status/spec/fixtures/cfn/stack-events-complete.json +0 -1080
  90. data/vendor/cfn-status/spec/fixtures/cfn/stack-events-in-progress.json +0 -1080
  91. data/vendor/cfn-status/spec/fixtures/cfn/stack-events-update-rollback-complete.json +0 -1086
  92. data/vendor/cfn-status/spec/lib/cfn_status_spec.rb +0 -153
  93. data/vendor/cfn-status/spec/spec_helper.rb +0 -14
@@ -7,7 +7,7 @@ module Jets::Builders
7
7
  # Then replace the binary gems.
8
8
  def build
9
9
  consolidate_gems_to_opt
10
- replace_compiled_gems
10
+ replace_compiled_gems unless Jets.config.gems.disable
11
11
  end
12
12
 
13
13
  # Also restructure the folder from:
@@ -17,13 +17,13 @@ module Jets::Builders
17
17
  #
18
18
  # For Lambda Layer structure
19
19
  def consolidate_gems_to_opt
20
- src = "#{stage_area}/code/vendor/gems/ruby/2.5.0"
21
- dest = "#{stage_area}/opt/ruby/gems/2.5.0"
20
+ src = "#{stage_area}/code/vendor/gems/ruby/#{Jets.ruby_folder}"
21
+ dest = "#{stage_area}/opt/ruby/gems/#{Jets.ruby_folder}"
22
22
  rsync_and_link(src, dest)
23
23
 
24
24
  return unless Jets.rack?
25
25
 
26
- src = "#{stage_area}/rack/vendor/gems/ruby/2.5.0"
26
+ src = "#{stage_area}/rack/vendor/gems/ruby/#{Jets.ruby_folder}"
27
27
  rsync_and_link(src, dest)
28
28
  end
29
29
 
@@ -59,7 +59,6 @@ module Jets::Builders
59
59
  project_root = "#{stage_area}/opt"
60
60
  headline "Replacing compiled gems with AWS Lambda Linux compiled versions: #{project_root}"
61
61
  options = {
62
- s3: "lambdagems2",
63
62
  build_root: cache_area, # used in jets-gems
64
63
  project_root: project_root, # used in gem_replacer and jets-gems
65
64
  }
@@ -12,10 +12,9 @@ module Jets::Builders
12
12
  def install
13
13
  return unless gemfile_exist?
14
14
 
15
- reconfigure_ruby_version
16
15
  clean_old_submodules
17
16
  bundle_install
18
- setup_bundle_config
17
+ copy_bundle_config
19
18
  copy_cache_gems
20
19
  end
21
20
 
@@ -46,6 +45,7 @@ module Jets::Builders
46
45
  headline "Bundling: running bundle install in cache area: #{cache_area}."
47
46
 
48
47
  copy_gemfiles(full_project_path)
48
+ copy_bundled_gems(full_project_path)
49
49
 
50
50
  # Uncomment out to always remove the cache/vendor/gems to debug
51
51
  # FileUtils.rm_rf("#{cache_area}/vendor/gems")
@@ -57,16 +57,17 @@ module Jets::Builders
57
57
  # bundle config gems.myprivatesource.com user:pass
58
58
  #
59
59
 
60
- FileUtils.rm_rf("#{cache_area}/.bundle")
60
+ create_bundle_config
61
61
  require "bundler" # dynamically require bundler so user can use any bundler
62
62
  Bundler.with_unbundled_env do
63
63
  sh(
64
64
  "cd #{cache_area} && " \
65
- "env bundle install --path #{cache_area}/vendor/gems --without development test"
65
+ "env bundle install"
66
66
  )
67
67
  end
68
+ create_bundle_config(frozen: true)
68
69
 
69
- remove_bundled_with("#{cache_area}/Gemfile.lock")
70
+ rewrite_gemfile_lock("#{cache_area}/Gemfile.lock")
70
71
 
71
72
  # Copy the Gemfile.lock back to the project in case it was updated.
72
73
  # For example we add the jets-rails to the Gemfile.
@@ -94,14 +95,6 @@ module Jets::Builders
94
95
  Tidy.new(path).cleanup!
95
96
  end
96
97
 
97
- # This is in case the user has a 2.5.x variant.
98
- # Force usage of ruby version that jets supports
99
- # The lambda server only has ruby 2.5.0 installed.
100
- def reconfigure_ruby_version
101
- ruby_version = "#{@full_app_root}/.ruby-version"
102
- IO.write(ruby_version, Jets::RUBY_VERSION)
103
- end
104
-
105
98
  # When using submodules, bundler leaves old submodules behind. Over time this inflates
106
99
  # the size of the the cache gems. So we'll clean it up.
107
100
  def clean_old_submodules
@@ -137,6 +130,12 @@ module Jets::Builders
137
130
  end
138
131
  end
139
132
 
133
+ def copy_bundled_gems(full_project_path)
134
+ src = "#{full_project_path}/bundled_gems"
135
+ return unless File.exist?(src)
136
+ Jets::Util.cp_r(src, "#{cache_area}/bundled_gems")
137
+ end
138
+
140
139
  def copy_gemfiles(full_project_path)
141
140
  FileUtils.mkdir_p(cache_area)
142
141
  FileUtils.cp("#{full_project_path}/Gemfile", "#{cache_area}/Gemfile")
@@ -150,9 +149,10 @@ module Jets::Builders
150
149
 
151
150
  # Remove the BUNDLED WITH line since we don't control the bundler gem version on AWS Lambda
152
151
  # And this can cause issues with require 'bundler/setup'
153
- def remove_bundled_with(gemfile_lock)
152
+ def rewrite_gemfile_lock(gemfile_lock)
154
153
  lines = IO.readlines(gemfile_lock)
155
154
 
155
+ # Remove BUNDLED WITH
156
156
  # amount is the number of lines to remove
157
157
  new_lines, capture, count, amount = [], true, 0, 2
158
158
  lines.each do |l|
@@ -166,13 +166,32 @@ module Jets::Builders
166
166
  end
167
167
  end
168
168
 
169
+ # Replace things like nokogiri (1.11.1-x86_64-darwin) => nokogiri (1.11.1)
170
+ lines, new_lines = new_lines, []
171
+ lines.each do |l|
172
+ if l.include?("-x86_64-darwin")
173
+ l = l.sub('-x86_64-darwin','')
174
+ end
175
+ new_lines << l
176
+ end
177
+
178
+ # Make sure platform is ruby
179
+ lines, new_lines, marker = new_lines, [], false
180
+ lines.each do |l|
181
+ if marker # the next loop has the platform we want to replace
182
+ new_lines << " ruby\n"
183
+ marker = false
184
+ next
185
+ end
186
+ marker = l.include?('PLATFORMS')
187
+ new_lines << l
188
+ end
189
+
169
190
  content = new_lines.join('')
170
191
  IO.write(gemfile_lock, content)
171
192
  end
172
193
 
173
- def setup_bundle_config
174
- ensure_build_cache_bundle_config_exists!
175
-
194
+ def copy_bundle_config
176
195
  # Override project's .bundle/config and ensure that .bundle/config matches
177
196
  # at these 2 spots:
178
197
  # app_root/.bundle/config
@@ -187,11 +206,12 @@ module Jets::Builders
187
206
  # this only happens with ssh debugging, not when the ci.sh script gets ran.
188
207
  # But on macosx it exists.
189
208
  # Dont know why this is the case.
190
- def ensure_build_cache_bundle_config_exists!
209
+ def create_bundle_config(frozen: false)
210
+ FileUtils.rm_rf("#{cache_area}/.bundle")
211
+ frozen_line = %Q|BUNDLE_FROZEN: "true"\n| if frozen
191
212
  text =<<-EOL
192
213
  ---
193
- BUNDLE_FROZEN: "true"
194
- BUNDLE_PATH: "vendor/gems"
214
+ #{frozen_line}BUNDLE_PATH: "vendor/gems"
195
215
  BUNDLE_WITHOUT: "development:test"
196
216
  EOL
197
217
  bundle_config = "#{cache_area}/.bundle/config"
@@ -81,8 +81,7 @@ module Jets::Builders
81
81
  # Reason do not remove the cache folder generally is because some gems have
82
82
  # actual cache folders that they used.
83
83
  def remove_gem_cache
84
- ruby_minor_version = Jets::RUBY_VERSION.split('.')[0..1].join('.') + '.0'
85
- cache_path = "#{@project_root}/vendor/gems/ruby/#{ruby_minor_version}/cache"
84
+ cache_path = "#{@project_root}/vendor/gems/ruby/#{Jets.ruby_folder}/cache"
86
85
  FileUtils.rm_rf(cache_path)
87
86
  end
88
87
 
data/lib/jets/bundle.rb CHANGED
@@ -15,6 +15,7 @@ module Jets
15
15
  # Later in Jets::Booter, Bundle.require is called and includes the Jets.env group.
16
16
  #
17
17
  def setup
18
+ return unless jets_project?
18
19
  return unless bundler_enabled?
19
20
  Kernel.require "bundler/setup"
20
21
  Bundler.setup # Same as Bundler.setup(:default)
@@ -38,6 +39,7 @@ module Jets
38
39
  # rescued gracefully. This is done in Jets::Commands::RakeTasks.load! In the case when user is in another
39
40
  # project with another Gemfile, the load errors will also be rescued.
40
41
  def require
42
+ return unless jets_project?
41
43
  return unless bundler_enabled?
42
44
  Kernel.require "bundler/setup"
43
45
  Bundler.require(*bundler_groups)
@@ -77,6 +79,10 @@ module Jets
77
79
  [:default, Jets.env.to_sym]
78
80
  end
79
81
 
82
+ def jets_project?
83
+ File.exist?("config/application.rb")
84
+ end
85
+
80
86
  extend self
81
87
  end
82
88
  end
@@ -1,5 +1,6 @@
1
1
  module Jets::Cfn::Builders
2
2
  class ApiGatewayBuilder
3
+ extend Memoist
3
4
  include Interface
4
5
  include Jets::AwsServices
5
6
 
@@ -43,22 +44,75 @@ module Jets::Cfn::Builders
43
44
  end
44
45
 
45
46
  def add_domain_name
46
- domain_name = Jets::Resource::ApiGateway::DomainName.new
47
- add_resource(domain_name)
48
- add_outputs(domain_name.outputs)
47
+ add_outputs(create_domain_name)
49
48
  end
50
49
 
51
50
  def add_route53_dns
52
51
  dns = Jets::Resource::Route53::RecordSet.new
53
- add_resource(dns)
54
- add_outputs(dns.outputs)
52
+ if !existing_domain_name?(dns.domain_name) or existing_dns_record_on_stack?
53
+ add_resource(dns)
54
+ add_outputs(dns.outputs)
55
+ end
56
+ end
57
+
58
+ def create_domain_name()
59
+ resource = Jets::Resource::ApiGateway::DomainName.new
60
+
61
+ return {
62
+ "DomainName" => resource.domain_name
63
+ } if (existing_domain_name?(resource) and !existing_domain_name_on_stack?)
64
+
65
+ add_resource(resource)
66
+ return resource.outputs
67
+ end
68
+
69
+ def existing_domain_name?(resource)
70
+ apigateway.get_domain_name({
71
+ domain_name: resource.domain_name
72
+ })
73
+ return true
74
+ rescue
75
+ return false
76
+ end
77
+ memoize :existing_domain_name?
78
+
79
+ def existing_domain_name_on_stack?
80
+ cfn.describe_stack_resource({
81
+ stack_name: api_gateway_physical_resource_id,
82
+ logical_resource_id: "DomainName"
83
+ })
84
+ return true
85
+ rescue
86
+ return false
87
+ end
88
+
89
+ def existing_dns_record_on_stack?
90
+ cfn.describe_stack_resource({
91
+ stack_name: api_gateway_physical_resource_id,
92
+ logical_resource_id: "DnsRecord"
93
+ })
94
+ return true
95
+ rescue
96
+ return false
97
+ end
98
+
99
+ def api_gateway_physical_resource_id
100
+ cfn.describe_stack_resource({
101
+ stack_name: Jets::Naming.parent_stack_name,
102
+ logical_resource_id: "ApiGateway"
103
+ })
104
+ .stack_resource_detail
105
+ .physical_resource_id
106
+ rescue
107
+ return nil
55
108
  end
109
+ memoize :api_gateway_physical_resource_id
56
110
 
57
111
  # Adds route related Resources and Outputs
58
112
  # Delegates to ApiResourcesBuilder
59
- PAGE_LIMIT = Integer(ENV['JETS_AWS_OUTPUTS_LIMIT'] || 60) # Allow override for testing
113
+ PAGE_LIMIT = Integer(ENV['JETS_AWS_OUTPUTS_LIMIT'] || 200) # Allow override for testing
60
114
  def add_gateway_routes
61
- # Reject homepage. Otherwise we have 60 - 1 resources on the first page.
115
+ # Reject homepage. Otherwise we have 200 - 1 resources on the first page.
62
116
  # There's a next call in ApiResources.add_gateway_resources to skip the homepage.
63
117
  all_paths = Jets::Router.all_paths.reject { |p| p == '' }
64
118
  all_paths.each_slice(PAGE_LIMIT).each_with_index do |paths, i|
data/lib/jets/cfn/ship.rb CHANGED
@@ -102,7 +102,7 @@ module Jets::Cfn
102
102
  end
103
103
 
104
104
  def clean_deploy_logs
105
- Jets::Commands::Clean::Log.new.clean_deploys
105
+ Jets::Commands::Clean::Log.new(@options).clean_deploys
106
106
  end
107
107
 
108
108
  def endpoint_unavailable?
@@ -146,6 +146,7 @@ module Jets::Cfn
146
146
  # domain_name is a method on the Jets::Resource::ApiGateway::Domain instance
147
147
  url = "https://#{domain_name.domain_name}"
148
148
  puts "Custom Domain: #{url}"
149
+ puts "App Domain: #{Jets.config.app.domain}" if Jets.config.app.domain
149
150
  end
150
151
 
151
152
  # All CloudFormation states listed here:
@@ -7,6 +7,13 @@ module Jets::Cfn
7
7
  include ActionView::Helpers::NumberHelper # number_to_human_size
8
8
 
9
9
  attr_reader :bucket_name
10
+
11
+ CONTENT_TYPES_BY_EXTENSION = {
12
+ '.css' => 'text/css',
13
+ '.js' => 'application/javascript',
14
+ '.html' => 'text/html'
15
+ }
16
+
10
17
  def initialize(bucket_name)
11
18
  @bucket_name = bucket_name
12
19
  end
@@ -90,8 +97,17 @@ module Jets::Cfn
90
97
 
91
98
  key = s3_key(full_path)
92
99
  obj = s3_resource.bucket(bucket_name).object(key)
93
- puts "Uploading s3://#{bucket_name}/#{key}" # uncomment to see and debug
94
- obj.upload_file(full_path, acl: "public-read", cache_control: cache_control)
100
+ puts "Uploading and setting content type for s3://#{bucket_name}/#{key}" # uncomment to see and debug
101
+ obj.upload_file(full_path, { acl: "public-read", cache_control: cache_control }.merge(content_type_headers(full_path)))
102
+ end
103
+
104
+ def content_type_headers(full_path)
105
+ content_type = CONTENT_TYPES_BY_EXTENSION[File.extname(full_path)]
106
+ if content_type
107
+ { content_type: content_type }
108
+ else
109
+ {}
110
+ end
95
111
  end
96
112
 
97
113
  def s3_key(full_path)
data/lib/jets/cli.rb CHANGED
@@ -135,12 +135,17 @@ class Jets::CLI
135
135
  return Jets::Commands::Base.klass_from_namespace(namespace)
136
136
  end
137
137
 
138
+ return unless jets_project?
138
139
  rake_task_found = Jets::Commands::RakeCommand.namespaced_commands.include?(full_command)
139
140
  if rake_task_found
140
141
  return Jets::Commands::RakeCommand
141
142
  end
142
143
  end
143
144
 
145
+ def jets_project?
146
+ File.exist?("config/application.rb")
147
+ end
148
+
144
149
  # ["-h", "-?", "--help", "-D", "help"]
145
150
  def help_flags
146
151
  Thor::HELP_MAPPINGS + ["help"]
@@ -161,7 +166,7 @@ class Jets::CLI
161
166
  shell.say "Commands:"
162
167
  shell.print_table(thor_list, :indent => 2, :truncate => true)
163
168
 
164
- unless rake_list.empty?
169
+ if jets_project? && !rake_list.empty?
165
170
  shell.say "\nCommands via rake:"
166
171
  shell.print_table(rake_list, :indent => 2, :truncate => true)
167
172
  end
@@ -138,7 +138,7 @@ class Jets::Commands::Base < Thor
138
138
  def eager_load!
139
139
  return if Jets::Turbo.afterburner?
140
140
 
141
- Jets::Autoloaders.once.eager_load
141
+ Jets::Autoloaders.cli.eager_load
142
142
  end
143
143
  memoize :eager_load!
144
144
  end
@@ -59,8 +59,9 @@ class Jets::Commands::Call
59
59
  payload: transformed_event, # "fileb://file-path/input.json", <= JSON
60
60
  qualifier: @qualifier, # "1",
61
61
  }
62
+
62
63
  begin
63
- resp = aws_lambda.invoke(options)
64
+ resp = lambda_client.invoke(options)
64
65
  rescue Aws::Lambda::Errors::ResourceNotFoundException
65
66
  puts "The function #{function_name} was not found. Maybe check the spelling or the AWS_PROFILE?".color(:red)
66
67
  return
@@ -166,4 +167,16 @@ class Jets::Commands::Call
166
167
  $stderr.puts(text)
167
168
  end
168
169
 
170
+ def lambda_client
171
+ opt = {}
172
+ opt = opt.merge({retry_limit: @options[:retry_limit]}) if @options[:retry_limit].present?
173
+ opt = opt.merge({http_read_timeout: @options[:read_timeout]}) if @options[:read_timeout].present?
174
+
175
+ if opt.empty?
176
+ aws_lambda
177
+ else
178
+ Aws::Lambda::Client.new(opt)
179
+ end
180
+ end
181
+
169
182
  end
@@ -2,7 +2,7 @@ module Jets::Commands
2
2
  class Clean < Jets::Commands::Base
3
3
  class_option :noop, type: :boolean, desc: "noop or dry-run mode"
4
4
  class_option :mute, type: :boolean, desc: "mute output"
5
- class_option :sure, type: :boolean, desc: "bypass are you sure prompt"
5
+ class_option :yes, type: :boolean, desc: "bypass are you sure prompt"
6
6
 
7
7
  desc "log", "Cleans CloudWatch log groups assocated with app"
8
8
  long_desc Help.text('clean:log')
@@ -11,7 +11,7 @@ class Jets::Commands::Clean
11
11
  end
12
12
 
13
13
  def are_you_sure?(message)
14
- return true if @options[:sure]
14
+ return true if @options[:yes]
15
15
 
16
16
  puts "Are you sure that you want to #{message}? (y/N)"
17
17
  yes = $stdin.gets.strip
@@ -0,0 +1,51 @@
1
+ module Jets::Commands
2
+ class Configure
3
+ extend Memoist
4
+
5
+ def initialize(options)
6
+ @options = options
7
+ end
8
+
9
+ def run
10
+ data = load_yaml
11
+ data['key'] = token
12
+ FileUtils.mkdir_p(File.dirname(path))
13
+ IO.write(path, YAML.dump(data))
14
+ puts "Updated #{pretty(path)}"
15
+ end
16
+
17
+ def load_yaml
18
+ if File.exist?(path)
19
+ YAML.load_file(path)
20
+ else
21
+ {}
22
+ end
23
+ rescue Psych::SyntaxError => e
24
+ puts "WARN: There was an error reading #{pretty(path)}".color(:yellow)
25
+ puts "WARN: #{e.class} #{e.message}".color(:yellow)
26
+ {}
27
+ end
28
+
29
+ def pretty(path)
30
+ path.sub(ENV['HOME'], '~')
31
+ end
32
+
33
+ def path
34
+ "#{ENV['HOME']}/.jets/config.yml"
35
+ end
36
+
37
+ def token
38
+ @options[:token] || prompt
39
+ end
40
+ memoize :token
41
+
42
+ def prompt
43
+ puts <<~EOL
44
+ You are about to configure your ~/.jets/config.yml
45
+ You can get a token from serverlessgems.com
46
+ EOL
47
+ print "Please provide your token: "
48
+ $stdin.gets.strip
49
+ end
50
+ end
51
+ end