convox_installer 1.0.8 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/convox/client.rb CHANGED
@@ -1,140 +1,184 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "logger"
4
- require "json"
5
- require "fileutils"
3
+ require 'logger'
4
+ require 'json'
5
+ require 'fileutils'
6
+ require 'rubygems'
7
+ require 'os'
8
+ require 'erb'
6
9
 
7
10
  module Convox
8
11
  class Client
9
- CONVOX_DIR = File.expand_path("~/.convox").freeze
10
- AUTH_FILE = File.join(CONVOX_DIR, "auth")
11
- HOST_FILE = File.join(CONVOX_DIR, "host")
12
+ CONVOX_CONFIG_DIR = if OS.mac?
13
+ # Convox v3 moved this to ~/Library/Preferences/convox/ on Mac
14
+ File.expand_path('~/Library/Preferences/convox').freeze
15
+ else
16
+ File.expand_path('~/.convox').freeze
17
+ end
18
+
19
+ AUTH_FILE = File.join(CONVOX_CONFIG_DIR, 'auth')
20
+ CURRENT_FILE = File.join(CONVOX_CONFIG_DIR, 'current')
12
21
 
13
22
  attr_accessor :logger, :config
14
23
 
24
+ def cli_version_string
25
+ return @cli_version_string if @cli_version_string
26
+
27
+ cli_version_string ||= `convox --version`
28
+ return unless $CHILD_STATUS.success?
29
+
30
+ @cli_version_string = cli_version_string.chomp
31
+ end
32
+
33
+ def cli_version
34
+ return unless cli_version_string.is_a?(String)
35
+
36
+ if cli_version_string.match?(/^\d+\.\d+\.\d+/)
37
+ @cli_version ||= Gem::Version.new(version_string)
38
+ end
39
+ @cli_version
40
+ end
41
+
42
+ def convox_2_cli?
43
+ return false unless cli_version_string.is_a?(String)
44
+
45
+ cli_version_string.match?(/^20\d+$/)
46
+ end
47
+
48
+ def convox_3_cli?
49
+ return false if !cli_version_string.is_a?(String) ||
50
+ convox_2_cli? ||
51
+ !cli_version_string.match?(/^\d+\.\d+\.\d+/)
52
+
53
+ cli_version = Gem::Version.new(cli_version_string)
54
+ cli_version >= Gem::Version.new('3.0.0') &&
55
+ cli_version < Gem::Version.new('4.0.0')
56
+ end
57
+
15
58
  def auth
16
59
  load_auth_from_file
17
60
  end
18
61
 
19
62
  def initialize(options = {})
20
- @logger = Logger.new(STDOUT)
63
+ @logger = Logger.new($stdout)
21
64
  logger.level = options[:log_level] || Logger::INFO
22
65
  @config = options[:config] || {}
23
66
  end
24
67
 
68
+ # Convox v3 creates a folder for each rack for the Terraform config
69
+ def rack_dir
70
+ stack_name = config.fetch(:stack_name)
71
+ File.join(CONVOX_CONFIG_DIR, 'racks', stack_name)
72
+ end
73
+
25
74
  def backup_convox_host_and_rack
26
- FileUtils.mkdir_p CONVOX_DIR
27
-
28
- %w[host rack].each do |f|
29
- path = File.join(CONVOX_DIR, f)
30
- if File.exist?(path)
31
- bak_file = "#{path}.bak"
32
- logger.info "Moving existing #{path} to #{bak_file}..."
33
- FileUtils.mv(path, bak_file)
34
- end
35
- end
75
+ FileUtils.mkdir_p CONVOX_CONFIG_DIR
76
+
77
+ path = File.join(CONVOX_CONFIG_DIR, 'current')
78
+ return unless File.exist?(path)
79
+
80
+ bak_file = "#{path}.bak"
81
+ logger.info "Moving existing #{path} to #{bak_file}..."
82
+ FileUtils.mv(path, bak_file)
36
83
  end
37
84
 
38
85
  def install_convox
39
- require_config(%i[ aws_region stack_name ])
86
+ require_config(%i[aws_region stack_name])
40
87
  region = config.fetch(:aws_region)
41
88
  stack_name = config.fetch(:stack_name)
42
89
 
43
90
  if rack_already_installed?
44
- logger.info "There is already a Convox stack named #{stack_name} " \
45
- "in the #{region} AWS region. Using this rack. "
91
+ logger.info "There is already a Convox rack named #{stack_name}. Using this rack."
92
+ logger.debug 'If you need to start over, you can run: ' \
93
+ "convox rack uninstall #{stack_name} " \
94
+ '(Make sure you export AWS_ACCESS_KEY_ID and ' \
95
+ "AWS_SECRET_ACCESS_KEY first.)\n" \
96
+ "If this fails, you can try deleting the rack directory: rm -rf #{rack_dir}"
46
97
  return true
47
98
  end
48
99
 
49
100
  require_config(%i[
50
- aws_region
51
- aws_access_key_id
52
- aws_secret_access_key
53
- stack_name
54
- instance_type
55
- ])
101
+ aws_region
102
+ aws_access_key_id
103
+ aws_secret_access_key
104
+ stack_name
105
+ instance_type
106
+ ])
56
107
 
57
108
  logger.info "Installing Convox (#{stack_name})..."
58
109
 
59
110
  env = {
60
- "AWS_REGION" => region,
61
- "AWS_ACCESS_KEY_ID" => config.fetch(:aws_access_key_id),
62
- "AWS_SECRET_ACCESS_KEY" => config.fetch(:aws_secret_access_key),
111
+ 'AWS_REGION' => region,
112
+ 'AWS_ACCESS_KEY_ID' => config.fetch(:aws_access_key_id),
113
+ 'AWS_SECRET_ACCESS_KEY' => config.fetch(:aws_secret_access_key)
63
114
  }
64
- command = %Q{rack install aws \
65
- --name "#{config.fetch(:stack_name)}" \
66
- "InstanceType=#{config.fetch(:instance_type)}" \
67
- "BuildInstance="}
115
+ command = %(rack install aws \
116
+ "#{config.fetch(:stack_name)}" \
117
+ "node_type=#{config.fetch(:instance_type)}" \
118
+ "region=#{config.fetch(:aws_region)}")
119
+ # us-east constantly has problems with the us-east-1c AZ:
120
+ # "Cannot create cluster 'ds-enterprise-cx3' because us-east-1c, the targeted
121
+ # availability zone, does not currently have sufficient capacity to support the cluster.
122
+ # Retry and choose from these availability zones:
123
+ # us-east-1a, us-east-1b, us-east-1d, us-east-1e, us-east-1f
124
+ if config.fetch(:aws_region) == 'us-east-1'
125
+ command += ' "availability_zones=us-east-1a,us-east-1b,us-east-1d,us-east-1e,us-east-1f"'
126
+ end
68
127
 
69
- run_convox_command!(command, env)
128
+ run_convox_command!(command, env, rack_arg: false)
70
129
  end
71
130
 
72
131
  def rack_already_installed?
73
- require_config(%i[ aws_region stack_name ])
132
+ require_config(%i[aws_region stack_name])
74
133
 
75
134
  return unless File.exist?(AUTH_FILE)
76
135
 
77
- region = config.fetch(:aws_region)
136
+ # region = config.fetch(:aws_region)
78
137
  stack_name = config.fetch(:stack_name)
138
+ return true if File.exist?(rack_dir)
79
139
 
80
- auth.each do |host, password|
81
- if host.match?(/^#{stack_name}-\d+\.#{region}\.elb\.amazonaws\.com$/)
82
- return true
83
- end
140
+ auth.each do |rack_name, _password|
141
+ return true if rack_name == stack_name
84
142
  end
85
143
  false
86
144
  end
87
145
 
88
- def validate_convox_auth_and_set_host!
89
- require_config(%i[ aws_region stack_name ])
90
-
91
- unless File.exist?(AUTH_FILE)
92
- raise "Could not find auth file at #{AUTH_FILE}!"
93
- end
94
-
95
- region = config.fetch(:aws_region)
96
- stack = config.fetch(:stack_name)
97
-
98
- match_count = 0
99
- matching_host = nil
100
- auth.each do |host, password|
101
- if host.match?(/^#{stack}-\d+\.#{region}\.elb\.amazonaws\.com$/)
102
- matching_host = host
103
- match_count += 1
104
- end
105
- end
146
+ # Auth for a detached rack is not saved in the auth file anymore.
147
+ # It can be found in the terraform state:
148
+ # ~/Library/Preferences/convox/racks/ds-enterprise-cx3/terraform.tfstate
149
+ # Under outputs/api/value. The API URL contains the convox username and API token as basic auth.
150
+ def validate_convox_rack_and_write_current!
151
+ require_config(%i[aws_region stack_name])
106
152
 
107
- if match_count == 1
108
- set_host(matching_host)
109
- return matching_host
153
+ unless rack_already_installed?
154
+ raise "Could not find rack terraform directory at: #{rack_dir}"
110
155
  end
111
156
 
112
- if match_count > 1
113
- error_message = "Found multiple matching hosts for "
114
- else
115
- error_message = "Could not find matching authentication for "
116
- end
117
- error_message += "region: #{region}, stack: #{stack}"
118
- raise error_message
157
+ # Tells the Convox CLI to use our terraform stack
158
+ stack_name = config.fetch(:stack_name)
159
+ write_current(stack_name)
160
+ stack_name
119
161
  end
120
162
 
121
- def set_host(host)
122
- logger.debug "Setting convox host to #{host} (in #{HOST_FILE})..."
123
- File.open(HOST_FILE, "w") { |f| f.puts host }
163
+ def write_current(rack_name)
164
+ logger.debug "Setting convox rack to #{rack_name} (in #{CURRENT_FILE})..."
165
+ current_hash = { name: rack_name, type: 'terraform' }
166
+ File.open(CURRENT_FILE, 'w') { |f| f.puts current_hash.to_json }
124
167
  end
125
168
 
126
- def validate_convox_rack!
169
+ def validate_convox_rack_api!
127
170
  require_config(%i[
128
- aws_region
129
- stack_name
130
- instance_type
131
- ])
132
- logger.debug "Validating that convox rack has the correct attributes..."
171
+ aws_region
172
+ stack_name
173
+ instance_type
174
+ ])
175
+ logger.debug 'Validating that convox rack has the correct attributes...'
176
+ # Convox 3 racks no longer return info about region or type. (These are blank strings.)
133
177
  {
134
- provider: "aws",
135
- region: config.fetch(:aws_region),
136
- type: config.fetch(:instance_type),
137
- name: config.fetch(:stack_name),
178
+ provider: 'aws',
179
+ # region: config.fetch(:aws_region),
180
+ # type: config.fetch(:instance_type),
181
+ name: config.fetch(:stack_name)
138
182
  }.each do |k, v|
139
183
  convox_value = convox_rack_data[k.to_s]
140
184
  if convox_value != v
@@ -142,15 +186,30 @@ module Convox
142
186
  "but was: '#{convox_value}'"
143
187
  end
144
188
  end
145
- logger.debug "=> Convox rack has the correct attributes."
189
+ logger.debug '=> Convox rack has the correct attributes.'
146
190
  true
147
191
  end
148
192
 
149
193
  def convox_rack_data
150
194
  @convox_rack_data ||= begin
151
- logger.debug "Fetching convox rack attributes..."
152
- convox_output = `convox api get /system`
153
- raise "convox command failed!" unless $?.success?
195
+ logger.debug 'Fetching convox rack attributes...'
196
+ command = "convox api get /system --rack #{config.fetch(:stack_name)}"
197
+ logger.debug "+ #{command}"
198
+ # It can take a while for the API to be ready.
199
+ start_time = Time.now
200
+ convox_output = nil
201
+ loop do
202
+ convox_output = `#{command}`
203
+ break if $CHILD_STATUS.success?
204
+
205
+ if Time.now - start_time > 360
206
+ raise 'Could not connect to Convox rack API!'
207
+ end
208
+
209
+ logger.debug 'Waiting for Convox rack API to be ready... (can take a few minutes)'
210
+ sleep 5
211
+ end
212
+
154
213
  JSON.parse(convox_output)
155
214
  end
156
215
  end
@@ -162,17 +221,19 @@ module Convox
162
221
  app_name = config.fetch(:convox_app_name)
163
222
 
164
223
  logger.info "Creating app: #{app_name}..."
165
- logger.info "=> Documentation: " \
166
- "https://docs.convox.com/deployment/creating-an-application"
224
+ logger.info '=> Documentation: ' \
225
+ 'https://docs.convox.com/reference/cli/apps/'
167
226
 
168
- run_convox_command! "apps create #{app_name} --wait"
227
+ # NOTE: --wait flags were removed in Convox 3. It now waits by default.
228
+ run_convox_command! "apps create #{app_name}"
169
229
 
170
230
  retries = 0
171
231
  loop do
172
232
  break if convox_app_exists?
233
+
173
234
  if retries > 5
174
235
  raise "Something went wrong while creating the #{app_name} app! " \
175
- "(Please wait a few moments and then restart the installation script.)"
236
+ '(Please wait a few moments and then restart the installation script.)'
176
237
  end
177
238
  logger.info "Waiting for #{app_name} to be ready..."
178
239
  sleep 3
@@ -183,9 +244,9 @@ module Convox
183
244
  end
184
245
 
185
246
  def set_default_app_for_directory!
186
- logger.info "Setting default app in ./.convox/app..."
187
- FileUtils.mkdir_p File.expand_path("./.convox")
188
- File.open(File.expand_path("./.convox/app"), "w") do |f|
247
+ logger.info 'Setting default app in ./.convox/app...'
248
+ FileUtils.mkdir_p File.expand_path('./.convox')
249
+ File.open(File.expand_path('./.convox/app'), 'w') do |f|
189
250
  f.puts config.fetch(:convox_app_name)
190
251
  end
191
252
  end
@@ -195,12 +256,12 @@ module Convox
195
256
  app_name = config.fetch(:convox_app_name)
196
257
 
197
258
  logger.debug "Looking for existing #{app_name} app..."
198
- convox_output = `convox api get /apps`
199
- raise "convox command failed!" unless $?.success?
259
+ convox_output = `convox api get /apps --rack #{config.fetch(:stack_name)}`
260
+ raise 'convox command failed!' unless $CHILD_STATUS.success?
200
261
 
201
262
  apps = JSON.parse(convox_output)
202
263
  apps.each do |app|
203
- if app["name"] == app_name
264
+ if app['name'] == app_name
204
265
  logger.debug "=> Found #{app_name} app."
205
266
  return true
206
267
  end
@@ -210,127 +271,117 @@ module Convox
210
271
  end
211
272
 
212
273
  # Create the s3 bucket, and also apply a CORS configuration
213
- def create_s3_bucket!
274
+ # Convox v3 update - They removed support for S3 resources, so we have to do
275
+ # in terraform now (which is actually pretty nice!)
276
+ def add_s3_bucket
214
277
  require_config(%i[s3_bucket_name])
215
- bucket_name = config.fetch(:s3_bucket_name)
216
- if s3_bucket_exists?
217
- logger.info "#{bucket_name} S3 bucket already exists!"
218
- else
219
- logger.info "Creating S3 bucket resource (#{bucket_name})..."
220
- run_convox_command! "rack resources create s3 " \
221
- "--name \"#{bucket_name}\" " \
222
- "--wait"
223
-
224
- retries = 0
225
- loop do
226
- break if s3_bucket_exists?
227
278
 
228
- if retries > 10
229
- raise "Something went wrong while creating the #{bucket_name} S3 bucket! " \
230
- "(Please wait a few moments and then restart the installation script.)"
231
- end
232
- logger.debug "Waiting for S3 bucket to be ready..."
233
- sleep 3
234
- retries += 1
235
- end
236
-
237
- logger.debug "=> S3 bucket created!"
279
+ unless config.key? :s3_bucket_cors_rule
280
+ logger.debug 'No CORS rule provided in config: s3_bucket_cors_rule (optional)'
281
+ return
238
282
  end
239
283
 
240
- set_s3_bucket_cors_policy
284
+ write_terraform_template('s3_bucket')
241
285
  end
242
286
 
243
- def s3_bucket_exists?
244
- require_config(%i[s3_bucket_name])
245
- bucket_name = config.fetch(:s3_bucket_name)
246
- logger.debug "Looking up S3 bucket resource: #{bucket_name}"
247
- `convox api get /resources/#{bucket_name} 2>/dev/null`
248
- $?.success?
287
+ def add_rds_database
288
+ require_config(%i[database_username database_password])
289
+ write_terraform_template('rds')
249
290
  end
250
291
 
251
- def s3_bucket_details
252
- require_config(%i[s3_bucket_name])
253
- @s3_bucket_details ||= begin
254
- bucket_name = config.fetch(:s3_bucket_name)
255
- logger.debug "Fetching S3 bucket resource details for #{bucket_name}..."
256
-
257
- response = `convox api get /resources/#{bucket_name}`
258
- raise "convox command failed!" unless $?.success?
259
-
260
- bucket_data = JSON.parse(response)
261
- s3_url = bucket_data["url"]
262
- matches = s3_url.match(
263
- /^s3:\/\/(?<access_key_id>[^:]*):(?<secret_access_key>[^@]*)@(?<bucket_name>.*)$/
264
- )
265
-
266
- match_keys = %i[access_key_id secret_access_key bucket_name]
267
- unless matches && match_keys.all? { |k| matches[k].present? }
268
- raise "#{s3_url} is an invalid S3 URL!"
269
- end
292
+ def add_elasticache_cluster
293
+ write_terraform_template('elasticache')
294
+ end
270
295
 
271
- {
272
- access_key_id: matches[:access_key_id],
273
- secret_access_key: matches[:secret_access_key],
274
- name: matches[:bucket_name],
275
- }
296
+ def write_terraform_template(name)
297
+ template_path = File.join(__dir__, "../../terraform/#{name}.tf.erb")
298
+ unless File.exist?(template_path)
299
+ raise "Could not find terraform template at: #{template_path}"
276
300
  end
301
+
302
+ template = ERB.new(File.read(template_path))
303
+ template_output = template.result(binding)
304
+
305
+ tf_file_path = File.join(rack_dir, "#{name}.tf")
306
+ logger.debug "Writing terraform config to #{tf_file_path}..."
307
+ File.open(tf_file_path, 'w') { |f| f.puts template_output }
277
308
  end
278
309
 
279
- def set_s3_bucket_cors_policy
280
- require_config(%i[aws_access_key_id aws_secret_access_key])
281
- access_key_id = config.fetch(:aws_access_key_id)
282
- secret_access_key = config.fetch(:aws_secret_access_key)
310
+ def apply_terraform_update!
311
+ logger.info 'Applying terraform update...'
312
+ command = if ENV['DEBUG_TERRAFORM']
313
+ 'terraform plan'
314
+ else
315
+ 'terraform apply -auto-approve'
316
+ end
317
+ logger.debug "+ #{command}"
283
318
 
284
- unless config.key? :s3_bucket_cors_policy
285
- logger.debug "No CORS policy provided in config: s3_bucket_cors_policy"
286
- return
319
+ env = {
320
+ 'AWS_ACCESS_KEY_ID' => config.fetch(:aws_access_key_id),
321
+ 'AWS_SECRET_ACCESS_KEY' => config.fetch(:aws_secret_access_key)
322
+ }
323
+ Dir.chdir(rack_dir) do
324
+ system env, command
325
+ raise 'terraform command failed!' unless $CHILD_STATUS.success?
287
326
  end
288
- cors_policy_string = config.fetch(:s3_bucket_cors_policy)
289
-
290
- bucket_name = s3_bucket_details[:name]
291
-
292
- logger.debug "Looking up existing CORS policy for #{bucket_name}"
293
- existing_cors_policy_string =
294
- `AWS_ACCESS_KEY_ID=#{access_key_id} \
295
- AWS_SECRET_ACCESS_KEY=#{secret_access_key} \
296
- aws s3api get-bucket-cors --bucket #{bucket_name} 2>/dev/null`
297
- if $?.success? && existing_cors_policy_string.present?
298
- # Sort all the nested arrays so that the equality operator works
299
- existing_cors_policy = JSON.parse(existing_cors_policy_string)
300
- cors_policy_json = JSON.parse(cors_policy_string)
301
- [existing_cors_policy, cors_policy_json].each do |policy_json|
302
- if policy_json.is_a?(Hash) && policy_json["CORSRules"]
303
- policy_json["CORSRules"].each do |rule|
304
- rule["AllowedHeaders"].sort! if rule["AllowedHeaders"]
305
- rule["AllowedMethods"].sort! if rule["AllowedMethods"]
306
- rule["AllowedOrigins"].sort! if rule["AllowedOrigins"]
307
- end
308
- end
309
- end
327
+ end
310
328
 
311
- if existing_cors_policy == cors_policy_json
312
- logger.debug "=> CORS policy is already up to date for #{bucket_name}."
313
- return
314
- end
329
+ def terraform_state
330
+ tf_state_file = File.join(rack_dir, 'terraform.tfstate')
331
+ JSON.parse(File.read(tf_state_file))
332
+ end
333
+
334
+ def terraform_resource(resource_type, resource_name)
335
+ resource = terraform_state['resources'].find do |resource|
336
+ resource['type'] == resource_type && resource['name'] == resource_name
315
337
  end
338
+ return resource if resource
316
339
 
317
- begin
318
- logger.info "Setting CORS policy for #{bucket_name}..."
340
+ raise "Could not find #{resource_type} resource named #{resource_name} in terraform state!"
341
+ end
342
+
343
+ def s3_bucket_details
344
+ require_config(%i[s3_bucket_name])
319
345
 
320
- File.open("cors-policy.json", "w") { |f| f.puts cors_policy_string }
346
+ s3_bucket = terraform_resource('aws_s3_bucket', 'docs_s3_bucket')
347
+ bucket_attributes = s3_bucket['instances'][0]['attributes']
348
+ access_key = terraform_resource('aws_iam_access_key', 'docspring_user_access_key')
349
+ key_attributes = access_key['instances'][0]['attributes']
321
350
 
322
- `AWS_ACCESS_KEY_ID=#{access_key_id} \
323
- AWS_SECRET_ACCESS_KEY=#{secret_access_key} \
324
- aws s3api put-bucket-cors \
325
- --bucket #{bucket_name} \
326
- --cors-configuration "file://cors-policy.json"`
327
- unless $?.success?
328
- raise "Something went wrong while setting the S3 bucket CORS policy!"
329
- end
330
- logger.info "=> Successfully set CORS policy for #{bucket_name}."
331
- ensure
332
- FileUtils.rm_f "cors-policy.json"
333
- end
351
+ {
352
+ access_key_id: key_attributes['id'],
353
+ secret_access_key: key_attributes['secret'],
354
+ name: bucket_attributes['bucket']
355
+ }
356
+ end
357
+
358
+ def rds_details
359
+ require_config(%i[database_username database_password])
360
+
361
+ database = terraform_resource('aws_db_instance', 'rds_database')
362
+ database_attributes = database['instances'][0]['attributes']
363
+
364
+ username = database_attributes['username']
365
+ password = database_attributes['password']
366
+ endpoint = database_attributes['endpoint']
367
+ postgres_url = "postgres://#{username}:#{password}@#{endpoint}/app"
368
+ {
369
+ postgres_url: postgres_url
370
+ }
371
+ end
372
+
373
+ def elasticache_details
374
+ require_config(%i[s3_bucket_name])
375
+
376
+ # Just ensure that the bucket exists in the state
377
+ cluster = terraform_resource('aws_elasticache_cluster', 'elasticache_cluster')
378
+ cluster_attributes = cluster['instances'][0]['attributes']
379
+ cache_node = cluster_attributes['cache_nodes'][0]
380
+ redis_url = "redis://#{cache_node['address']}:#{cache_node['port']}/0"
381
+
382
+ {
383
+ redis_url: redis_url
384
+ }
334
385
  end
335
386
 
336
387
  def add_docker_registry!
@@ -338,52 +389,54 @@ module Convox
338
389
 
339
390
  registry_url = config.fetch(:docker_registry_url)
340
391
 
341
- logger.debug "Looking up existing Docker registries..."
342
- registries_response = `convox api get /registries`
343
- unless $?.success?
344
- raise "Something went wrong while fetching the list of registries!"
392
+ logger.debug 'Looking up existing Docker registries...'
393
+ registries_response = `convox api get /registries --rack #{config.fetch(:stack_name)}`
394
+ unless $CHILD_STATUS.success?
395
+ raise 'Something went wrong while fetching the list of registries!'
345
396
  end
397
+
346
398
  registries = JSON.parse(registries_response)
347
399
 
348
- if registries.any? { |r| r["server"] == registry_url }
400
+ if registries.any? { |r| r['server'] == registry_url }
349
401
  logger.debug "=> Docker Registry already exists: #{registry_url}"
350
402
  return true
351
403
  end
352
404
 
353
405
  logger.info "Adding Docker Registry: #{registry_url}..."
354
- logger.info "=> Documentation: " \
355
- "https://docs.convox.com/deployment/private-registries"
406
+ logger.info '=> Documentation: ' \
407
+ 'https://docs.convox.com/configuration/private-registries/'
356
408
 
357
409
  `convox registries add "#{registry_url}" \
358
410
  "#{config.fetch(:docker_registry_username)}" \
359
- "#{config.fetch(:docker_registry_password)}"`
360
- unless $?.success?
361
- raise "Something went wrong while adding the #{registry_url} registry!"
362
- end
411
+ "#{config.fetch(:docker_registry_password)}" \
412
+ --rack #{config.fetch(:stack_name)}`
413
+ return if $CHILD_STATUS.success?
414
+
415
+ raise "Something went wrong while adding the #{registry_url} registry!"
363
416
  end
364
417
 
365
418
  def default_service_domain_name
366
- require_config(%i[convox_app_name default_service])
367
-
368
- @default_service_domain_name ||= begin
369
- convox_domain = convox_rack_data["domain"]
370
- elb_name_and_region = convox_domain[/([^\.]*\.[^\.]*)\..*/, 1]
371
- unless elb_name_and_region.present?
372
- raise "Something went wrong while parsing the ELB name and region! " \
373
- "(#{elb_name_and_region})"
374
- end
375
- app = config.fetch(:convox_app_name)
376
- service = config.fetch(:default_service)
419
+ require_config(%i[convox_app_name])
377
420
 
378
- # Need to return downcase host so that `config.hosts` works with Rails applications
379
- "#{app}-#{service}.#{elb_name_and_region}.convox.site".downcase
380
- end
421
+ app_name = config.fetch(:convox_app_name)
422
+ default_service = config[:default_service] || 'web'
423
+
424
+ convox_api_url = terraform_state['outputs']['api']['value']
425
+ convox_router_host = convox_api_url.split('@').last.sub(/^api\./, '')
426
+
427
+ [default_service, app_name, convox_router_host].join('.').downcase
381
428
  end
382
429
 
383
- def run_convox_command!(cmd, env = {})
430
+ def run_convox_command!(cmd, env = {}, rack_arg: true)
431
+ # Always include the rack as an argument, to
432
+ # make sure that 'convox switch' doesn't affect any commands
384
433
  command = "convox #{cmd}"
434
+ if rack_arg
435
+ command = "#{command} --rack #{config.fetch(:stack_name)}"
436
+ end
437
+ logger.debug "+ #{command}"
385
438
  system env, command
386
- raise "Error running: #{command}" unless $?.success?
439
+ raise "Error running: #{command}" unless $CHILD_STATUS.success?
387
440
  end
388
441
 
389
442
  private
@@ -393,7 +446,7 @@ module Convox
393
446
 
394
447
  begin
395
448
  JSON.parse(File.read(AUTH_FILE))
396
- rescue
449
+ rescue StandardError
397
450
  {}
398
451
  end
399
452
  end
data/lib/convox.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "convox/client"
3
+ require 'convox/client'