convox_installer 1.0.8 → 3.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.
@@ -1,48 +1,54 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "highline"
4
- require "fileutils"
5
- require "json"
6
- require "securerandom"
3
+ require 'highline'
4
+ require 'fileutils'
5
+ require 'json'
6
+ require 'securerandom'
7
7
 
8
8
  module ConvoxInstaller
9
9
  class Config
10
- CONFIG_FILE = File.expand_path("./.installer_config.json").freeze
10
+ CONFIG_FILE = File.expand_path('./.installer_config.json').freeze
11
11
 
12
12
  attr_accessor :logger, :config, :prompts, :highline
13
13
 
14
14
  DEFAULT_PROMPTS = [
15
15
  {
16
16
  key: :stack_name,
17
- title: "Convox Stack Name",
18
- prompt: "Please enter a name for your Convox installation",
19
- default: "convox",
17
+ title: 'Convox Stack Name',
18
+ prompt: 'Please enter a name for your Convox installation',
19
+ default: 'convox'
20
20
  },
21
21
  {
22
22
  key: :aws_region,
23
- title: "AWS Region",
24
- default: "us-east-1",
23
+ title: 'AWS Region',
24
+ default: 'us-east-1'
25
25
  },
26
26
  {
27
27
  key: :instance_type,
28
- title: "EC2 Instance Type",
29
- default: "t3.medium",
28
+ title: 'EC2 Instance Type',
29
+ default: 't3.medium'
30
30
  },
31
31
  {
32
- section: "Admin AWS Credentials",
32
+ section: 'Admin AWS Credentials'
33
33
  },
34
34
  {
35
35
  key: :aws_access_key_id,
36
- title: "AWS Access Key ID",
36
+ title: 'AWS Access Key ID'
37
37
  },
38
38
  {
39
39
  key: :aws_secret_access_key,
40
- title: "AWS Secret Access Key",
40
+ title: 'AWS Secret Access Key'
41
41
  },
42
+ # Short random ID used to ensure that resources are always unique
43
+ {
44
+ key: :random_id,
45
+ value: -> { SecureRandom.hex(4) },
46
+ hidden: true
47
+ }
42
48
  ].freeze
43
49
 
44
50
  def initialize(options = {})
45
- @logger = Logger.new(STDOUT)
51
+ @logger = Logger.new($stdout)
46
52
  logger.level = options[:log_level] || Logger::INFO
47
53
 
48
54
  self.prompts = options[:prompts] || DEFAULT_PROMPTS
@@ -74,13 +80,16 @@ module ConvoxInstaller
74
80
 
75
81
  @completed_prompt = true
76
82
 
77
- highline.say "Please double check all of these configuration details."
83
+ highline.say 'Please double check all of these configuration details.'
84
+
85
+ break if ENV['AUTOSTART_CONVOX_INSTALLATION']
78
86
 
79
87
  agree = highline.agree(
80
- "Would you like to start the Convox installation?" \
88
+ 'Would you like to start the Convox installation?' \
81
89
  " (press 'n' to correct any settings)"
82
90
  )
83
91
  break if agree
92
+
84
93
  highline.say "\n"
85
94
  end
86
95
 
@@ -89,7 +98,7 @@ module ConvoxInstaller
89
98
 
90
99
  def show_config_summary
91
100
  highline.say "\n============================================"
92
- highline.say " SUMMARY"
101
+ highline.say ' SUMMARY'
93
102
  highline.say "============================================\n\n"
94
103
 
95
104
  config_titles = prompts.map do |prompt|
@@ -106,10 +115,18 @@ module ConvoxInstaller
106
115
  highline.say " #{padded_key} #{value}"
107
116
  end
108
117
  highline.say "\nWe've saved your configuration to: #{CONFIG_FILE}"
109
- highline.say "If anything goes wrong during the installation, " \
118
+ highline.say 'If anything goes wrong during the installation, ' \
110
119
  "you can restart the script to reload the config and continue.\n\n"
111
120
  end
112
121
 
122
+ def self.config_file_exists?
123
+ File.exist?(CONFIG_FILE)
124
+ end
125
+
126
+ def self.read_config_file
127
+ File.read(CONFIG_FILE)
128
+ end
129
+
113
130
  private
114
131
 
115
132
  def ask_prompt(prompt)
@@ -129,7 +146,11 @@ module ConvoxInstaller
129
146
  return if config[key]
130
147
 
131
148
  default = prompt[:value]
132
- config[key] = default.is_a?(Proc) ? default.call(config) : default
149
+ config[key] = if default.is_a?(Proc)
150
+ default.arity.zero? ? default.call : default.call(config)
151
+ else
152
+ default
153
+ end
133
154
  save_config_to_file
134
155
  return
135
156
  end
@@ -153,7 +174,7 @@ module ConvoxInstaller
153
174
 
154
175
  logger.debug "Loading saved config from #{CONFIG_FILE}..."
155
176
 
156
- loaded_config = JSON.parse(Config.read_config_file)["config"].symbolize_keys
177
+ loaded_config = JSON.parse(Config.read_config_file)['config'].symbolize_keys
157
178
  self.config = config.merge(loaded_config)
158
179
  end
159
180
 
@@ -174,13 +195,5 @@ module ConvoxInstaller
174
195
  f.puts(JSON.pretty_generate(config: config))
175
196
  end
176
197
  end
177
-
178
- def self.config_file_exists?
179
- File.exist?(CONFIG_FILE)
180
- end
181
-
182
- def self.read_config_file
183
- File.read(CONFIG_FILE)
184
- end
185
198
  end
186
199
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "highline"
4
- require "os"
5
- require "logger"
3
+ require 'highline'
4
+ require 'os'
5
+ require 'logger'
6
6
 
7
7
  module ConvoxInstaller
8
8
  class Requirements
@@ -10,46 +10,66 @@ module ConvoxInstaller
10
10
 
11
11
  def initialize(options = {})
12
12
  @ecr_label = options[:ecr_label]
13
- @logger = Logger.new(STDOUT)
13
+ @logger = Logger.new($stdout)
14
14
  logger.level = options[:log_level] || Logger::INFO
15
15
  end
16
16
 
17
17
  def ensure_requirements!
18
- logger.debug "Checking for required commands..."
18
+ logger.debug 'Checking for required commands...'
19
19
 
20
20
  @missing_packages = []
21
- unless has_command? "convox"
21
+ unless command_present? 'convox'
22
22
  @missing_packages << {
23
- name: "convox",
24
- brew: "convox",
25
- docs: "https://docs.convox.com/introduction/installation",
23
+ name: 'convox',
24
+ brew: 'convox',
25
+ docs: 'https://docs.convox.com/introduction/installation'
26
26
  }
27
27
  end
28
28
 
29
- unless has_command? "aws"
29
+ unless command_present? 'aws'
30
30
  @missing_packages << {
31
- name: "aws",
32
- brew: "awscli",
33
- docs: "https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html",
31
+ name: 'aws',
32
+ brew: 'awscli',
33
+ docs: 'https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html'
34
+ }
35
+ end
36
+
37
+ unless command_present? 'terraform'
38
+ @missing_packages << {
39
+ name: 'terraform',
40
+ brew: 'terraform',
41
+ docs: 'https://learn.hashicorp.com/tutorials/terraform/install-cli'
34
42
  }
35
43
  end
36
44
 
37
45
  if @missing_packages.any?
38
- logger.error "This script requires the convox and AWS CLI tools."
46
+ logger.error 'This script requires the convox and AWS CLI tools.'
39
47
  if OS.mac?
40
- logger.error "Please run: brew install " \
41
- "#{@missing_packages.map { |p| p[:brew] }.join(" ")}"
48
+ logger.error 'Please run: brew install ' \
49
+ "#{@missing_packages.map { |p| p[:brew] }.join(' ')}"
42
50
  else
43
- logger.error "Installation Instructions:"
51
+ logger.error 'Installation Instructions:'
44
52
  @missing_packages.each do |package|
45
53
  logger.error "* #{package[:name]}: #{package[:docs]}"
46
54
  end
47
55
  end
48
56
  quit!
49
57
  end
58
+
59
+ client = Convox::Client.new
60
+ if client.convox_3_cli?
61
+ logger.debug "=> Convox CLI is version 3.x.x (#{client.cli_version_string})"
62
+ return
63
+ end
64
+
65
+ logger.error 'This script requires Convox CLI version 3.x.x. ' \
66
+ "Your Convox CLI version is: #{client.cli_version_string}"
67
+ logger.error "Please run 'brew update convox' or follow the instructions " \
68
+ 'at https://docs.convox.com/getting-started/introduction'
69
+ quit!
50
70
  end
51
71
 
52
- def has_command?(command)
72
+ def command_present?(command)
53
73
  path = find_command command
54
74
  if path.present?
55
75
  logger.debug "=> Found #{command}: #{path}"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ConvoxInstaller
4
- VERSION = "1.0.8"
4
+ VERSION = '3.0.0'
5
5
  end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support"
4
- require "active_support/core_ext"
5
- require "convox_installer/config"
6
- require "convox_installer/requirements"
7
- require "convox"
3
+ require 'active_support'
4
+ require 'active_support/core_ext'
5
+ require 'convox_installer/config'
6
+ require 'convox_installer/requirements'
7
+ require 'convox'
8
8
 
9
9
  module ConvoxInstaller
10
10
  def client
@@ -12,7 +12,7 @@ module ConvoxInstaller
12
12
  end
13
13
 
14
14
  def config
15
- options = {log_level: @log_level}
15
+ options = { log_level: @log_level }
16
16
  options[:prompts] = @prompts if @prompts
17
17
  @config ||= Config.new(options)
18
18
  end
@@ -32,18 +32,24 @@ module ConvoxInstaller
32
32
  %w[
33
33
  backup_convox_host_and_rack
34
34
  install_convox
35
- validate_convox_auth_and_set_host!
36
- validate_convox_rack!
35
+ validate_convox_rack_and_write_current!
36
+ validate_convox_rack_api!
37
37
  convox_rack_data
38
38
  create_convox_app!
39
39
  set_default_app_for_directory!
40
- create_s3_bucket!
41
- set_s3_bucket_cors_policy
40
+ add_s3_bucket
41
+ add_rds_database
42
+ add_elasticache_cluster
43
+ apply_terraform_update!
44
+ terraform_state
42
45
  s3_bucket_details
46
+ elasticache_details
47
+ rds_details
43
48
  add_docker_registry!
44
49
  default_service_domain_name
45
50
  run_convox_command!
46
51
  logger
52
+ rack_already_installed?
47
53
  ].each do |method|
48
54
  define_method(method) do |*args|
49
55
  client.send(method, *args)
@@ -1,20 +1,54 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "convox/client"
3
+ require 'convox/client'
4
4
 
5
5
  RSpec.describe Convox::Client do
6
- let(:home_dir) { File.expand_path("~") }
6
+ let(:home_dir) { File.expand_path('~') }
7
7
 
8
- it "finds the authentication details in ~/.convox/auth" do
8
+ it 'finds the authentication details in ~/.convox/auth' do
9
9
  expect(File).to receive(:exist?).with("#{home_dir}/.convox/auth").and_return(true)
10
10
  expect(File).to receive(:read).with("#{home_dir}/.convox/auth").and_return(
11
11
  '{ "test.example.com": "1234567890" }'
12
12
  )
13
13
  client = described_class.new
14
- expect(client.auth).to eq("test.example.com" => "1234567890")
14
+ expect(client.auth).to eq('test.example.com' => '1234567890')
15
15
  end
16
16
 
17
- it "should backup existing Convox host and rack files" do
17
+ describe 'Convox CLI version' do
18
+ let(:client) { described_class.new }
19
+
20
+ it 'returns the convox CLI version output for 20210208170413' do
21
+ expect(client).to receive(:cli_version_string).at_least(:once).and_return('20210208170413')
22
+ expect(client.convox_2_cli?).to be true
23
+ expect(client.convox_3_cli?).to be false
24
+ end
25
+
26
+ it 'returns the convox CLI version output for 20200101130413' do
27
+ expect(client).to receive(:cli_version_string).at_least(:once).and_return('20200101130413')
28
+ expect(client.convox_2_cli?).to be true
29
+ expect(client.convox_3_cli?).to be false
30
+ end
31
+
32
+ it 'returns the convox CLI version output for 3.0.0' do
33
+ expect(client).to receive(:cli_version_string).at_least(:once).and_return('3.0.0')
34
+ expect(client.convox_2_cli?).to be false
35
+ expect(client.convox_3_cli?).to be true
36
+ end
37
+
38
+ it 'returns the convox CLI version output for 3.1.3' do
39
+ expect(client).to receive(:cli_version_string).at_least(:once).and_return('3.1.3')
40
+ expect(client.convox_2_cli?).to be false
41
+ expect(client.convox_3_cli?).to be true
42
+ end
43
+
44
+ it 'returns the convox CLI version output for 4.0.0' do
45
+ expect(client).to receive(:cli_version_string).at_least(:once).and_return('4.0.0')
46
+ expect(client.convox_2_cli?).to be false
47
+ expect(client.convox_3_cli?).to be false
48
+ end
49
+ end
50
+
51
+ it 'backups existing Convox host and rack files' do
18
52
  expect(File).to receive(:exist?).with(
19
53
  "#{home_dir}/.convox/host"
20
54
  ).and_return(true)
@@ -34,61 +68,63 @@ RSpec.describe Convox::Client do
34
68
  client.backup_convox_host_and_rack
35
69
  end
36
70
 
37
- describe "#install" do
38
- it "should require the correct config vars" do
71
+ describe '#install' do
72
+ it 'requires the correct config vars' do
39
73
  client = described_class.new
40
- expect { client.install_convox }.to raise_error("aws_region is missing from the config!")
74
+ expect { client.install_convox }.to raise_error('aws_region is missing from the config!')
41
75
 
42
- client = described_class.new(config: {aws_region: "us-east-1"})
43
- expect { client.install_convox }.to raise_error("stack_name is missing from the config!")
76
+ client = described_class.new(config: { aws_region: 'us-east-1' })
77
+ expect { client.install_convox }.to raise_error('stack_name is missing from the config!')
44
78
  end
45
79
 
46
- it "should run the correct convox CLI command" do
80
+ it 'runs the correct convox CLI command' do
47
81
  client = described_class.new(
48
82
  config: {
49
- aws_region: "us-east-1",
50
- aws_access_key_id: "asdf",
51
- aws_secret_access_key: "1234",
52
- stack_name: "asdf",
53
- instance_type: "t3.medium",
54
- },
83
+ aws_region: 'us-east-1',
84
+ aws_access_key_id: 'asdf',
85
+ aws_secret_access_key: '1234',
86
+ stack_name: 'asdf',
87
+ instance_type: 't3.medium'
88
+ }
55
89
  )
56
90
 
57
91
  expect(client.logger).to receive(:info)
58
92
  expect(client).to receive(:run_convox_command!).with(
59
- "rack install aws --name \"asdf\" \"InstanceType=t3.medium\" " \
60
- "\"BuildInstance=\"",
61
- "AWS_ACCESS_KEY_ID" => "asdf",
62
- "AWS_REGION" => "us-east-1",
63
- "AWS_SECRET_ACCESS_KEY" => "1234",
93
+ 'rack install aws --name "asdf" "InstanceType=t3.medium" ' \
94
+ '"BuildInstance="',
95
+ 'AWS_ACCESS_KEY_ID' => 'asdf',
96
+ 'AWS_REGION' => 'us-east-1',
97
+ 'AWS_SECRET_ACCESS_KEY' => '1234'
64
98
  )
65
99
  client.install_convox
66
100
  end
67
101
  end
68
102
 
69
- describe "#validate_convox_auth_and_set_host!" do
70
- it "should require the correct config vars" do
103
+ describe '#validate_convox_auth_and_write_host!' do
104
+ it 'requires the correct config vars' do
71
105
  client = described_class.new
72
- expect { client.validate_convox_auth_and_set_host! }.to raise_error("aws_region is missing from the config!")
106
+ expect do
107
+ client.validate_convox_auth_and_write_host!
108
+ end.to raise_error('aws_region is missing from the config!')
73
109
  end
74
110
 
75
- it "should raise an error if auth file is missing" do
111
+ it 'raises an error if auth file is missing' do
76
112
  client = described_class.new(
77
113
  config: {
78
- aws_region: "us-east-1",
79
- stack_name: "asdf",
80
- },
114
+ aws_region: 'us-east-1',
115
+ stack_name: 'asdf'
116
+ }
81
117
  )
82
118
  expect(File).to receive(:exist?).with(
83
119
  "#{home_dir}/.convox/auth"
84
120
  ).and_return(false)
85
121
 
86
- expect {
87
- client.validate_convox_auth_and_set_host!
88
- }.to raise_error(/Could not find auth file at /)
122
+ expect do
123
+ client.validate_convox_auth_and_write_host!
124
+ end.to raise_error(/Could not find auth file at /)
89
125
  end
90
126
 
91
- it "should set ~/.convox/host if a matching host is found in the auth file" do
127
+ it 'sets ~/.convox/host if a matching host is found in the auth file' do
92
128
  expect(File).to receive(:exist?).with(
93
129
  "#{home_dir}/.convox/auth"
94
130
  ).twice.and_return(true)
@@ -98,19 +134,19 @@ RSpec.describe Convox::Client do
98
134
  )
99
135
  client = described_class.new(
100
136
  config: {
101
- aws_region: "us-west-2",
102
- stack_name: "convox-test",
103
- },
137
+ aws_region: 'us-west-2',
138
+ stack_name: 'convox-test'
139
+ }
104
140
  )
105
- expect(client).to receive(:set_host).with(
106
- "convox-test-697645520.us-west-2.elb.amazonaws.com"
141
+ expect(client).to receive(:write_current).with(
142
+ 'convox-test-697645520.us-west-2.elb.amazonaws.com'
107
143
  )
108
- expect(client.validate_convox_auth_and_set_host!).to(
109
- eq("convox-test-697645520.us-west-2.elb.amazonaws.com")
144
+ expect(client.validate_convox_auth_and_write_host!).to(
145
+ eq('convox-test-697645520.us-west-2.elb.amazonaws.com')
110
146
  )
111
147
  end
112
148
 
113
- it "should raise an error if no matching host is found" do
149
+ it 'raises an error if no matching host is found' do
114
150
  expect(File).to receive(:exist?).with(
115
151
  "#{home_dir}/.convox/auth"
116
152
  ).twice.and_return(true)
@@ -120,17 +156,17 @@ RSpec.describe Convox::Client do
120
156
  )
121
157
  client = described_class.new(
122
158
  config: {
123
- aws_region: "us-east-1",
124
- stack_name: "convox-test",
125
- },
159
+ aws_region: 'us-east-1',
160
+ stack_name: 'convox-test'
161
+ }
126
162
  )
127
- expect {
128
- client.validate_convox_auth_and_set_host!
129
- }.to raise_error("Could not find matching authentication for " \
130
- "region: us-east-1, stack: convox-test")
163
+ expect do
164
+ client.validate_convox_auth_and_write_host!
165
+ end.to raise_error('Could not find matching authentication for ' \
166
+ 'region: us-east-1, stack: convox-test')
131
167
  end
132
168
 
133
- it "should raise an error if it finds multiple matching hosts" do
169
+ it 'raises an error if it finds multiple matching hosts' do
134
170
  expect(File).to receive(:exist?).with(
135
171
  "#{home_dir}/.convox/auth"
136
172
  ).twice.and_return(true)
@@ -141,14 +177,14 @@ RSpec.describe Convox::Client do
141
177
  )
142
178
  client = described_class.new(
143
179
  config: {
144
- aws_region: "us-west-2",
145
- stack_name: "convox-test",
146
- },
180
+ aws_region: 'us-west-2',
181
+ stack_name: 'convox-test'
182
+ }
147
183
  )
148
- expect {
149
- client.validate_convox_auth_and_set_host!
150
- }.to raise_error("Found multiple matching hosts for " \
151
- "region: us-west-2, stack: convox-test")
184
+ expect do
185
+ client.validate_convox_auth_and_write_host!
186
+ end.to raise_error('Found multiple matching hosts for ' \
187
+ 'region: us-west-2, stack: convox-test')
152
188
  end
153
189
  end
154
190
  end