satorix 0.0.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +4 -1
- data/.gitlab-ci.yml +45 -0
- data/.rspec +2 -1
- data/.rubocop.yml +11 -0
- data/.ruby-version +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +25 -0
- data/Procfile +1 -0
- data/README.md +93 -1
- data/Rakefile +8 -4
- data/bin/console +3 -3
- data/bin/satorix +8 -0
- data/lib/satorix.rb +338 -2
- data/lib/satorix/CI/deploy/flynn.rb +129 -0
- data/lib/satorix/CI/deploy/flynn/environment_variables.rb +121 -0
- data/lib/satorix/CI/deploy/flynn/resources.rb +77 -0
- data/lib/satorix/CI/deploy/flynn/routes.rb +266 -0
- data/lib/satorix/CI/deploy/flynn/scale.rb +52 -0
- data/lib/satorix/CI/shared/buildpack_manager.rb +213 -0
- data/lib/satorix/CI/shared/buildpack_manager/buildpack.rb +153 -0
- data/lib/satorix/CI/shared/ruby/gem_manager.rb +79 -0
- data/lib/satorix/CI/shared/yarn_manager.rb +22 -0
- data/lib/satorix/CI/test/python/django_test.rb +35 -0
- data/lib/satorix/CI/test/python/safety.rb +27 -0
- data/lib/satorix/CI/test/ruby/brakeman.rb +32 -0
- data/lib/satorix/CI/test/ruby/bundler_audit.rb +32 -0
- data/lib/satorix/CI/test/ruby/cucumber.rb +26 -0
- data/lib/satorix/CI/test/ruby/rails_test.rb +26 -0
- data/lib/satorix/CI/test/ruby/rspec.rb +26 -0
- data/lib/satorix/CI/test/ruby/rubocop.rb +98 -0
- data/lib/satorix/CI/test/shared/database.rb +74 -0
- data/lib/satorix/shared/console.rb +180 -0
- data/lib/satorix/version.rb +1 -1
- data/satorix.gemspec +13 -11
- data/satorix/CI/deploy/ie_gem_server.rb +76 -0
- data/satorix/CI/deploy/rubygems.rb +77 -0
- data/satorix/custom.rb +21 -0
- metadata +57 -29
- data/.travis.yml +0 -5
@@ -0,0 +1,129 @@
|
|
1
|
+
module Satorix
|
2
|
+
module CI
|
3
|
+
module Deploy
|
4
|
+
module Flynn
|
5
|
+
|
6
|
+
include Satorix
|
7
|
+
include Satorix::Shared::Console
|
8
|
+
|
9
|
+
require_relative 'flynn/environment_variables'
|
10
|
+
include EnvironmentVariables
|
11
|
+
|
12
|
+
require_relative 'flynn/resources'
|
13
|
+
include Resources
|
14
|
+
|
15
|
+
require_relative 'flynn/routes'
|
16
|
+
include Routes
|
17
|
+
|
18
|
+
require_relative 'flynn/scale'
|
19
|
+
include Scale
|
20
|
+
|
21
|
+
extend self
|
22
|
+
|
23
|
+
|
24
|
+
def go
|
25
|
+
log_bench('Adding a local reference to the remote Flynn cluster...') { add_cluster }
|
26
|
+
log_bench('Creating Flynn project...') { create_project }
|
27
|
+
log_bench('Adding Flynn remote to CI local git...') { add_remote }
|
28
|
+
log_bench('Adjusting Flynn environment variables...') { adjust_env_vars }
|
29
|
+
log_bench('Configuring Flynn inactive slug release count...') { configure_inactive_slug_releases }
|
30
|
+
log_bench('Setting resources...') { set_resources }
|
31
|
+
log_bench('Deploying to Flynn...') { deploy }
|
32
|
+
log_bench('Running Database migrations...') { run_database_migrations } if run_database_migrations?
|
33
|
+
log_bench('Scaling application processes...') { adjust_scale }
|
34
|
+
log_bench('Setting up routes...') { setup_routes }
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def skip_buildpack
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def add_cluster
|
44
|
+
run_command(['flynn', 'cluster', 'add', '--force', '--default', "--tls-pin=#{ tls_pin }", cluster_name, domain_for_cluster, key], filtered_text: [tls_pin, key])
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def add_remote
|
49
|
+
run_command(['flynn', '-a', project_name, 'remote', 'add', cluster_name, '-y'])
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def cluster_name
|
54
|
+
domain_for_cluster
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def configure_inactive_slug_releases
|
59
|
+
run_command(%w[flynn meta set gc.max_inactive_slug_releases=2])
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def create_project
|
64
|
+
if project_exists?
|
65
|
+
log("Skipping - Flynn project '#{ project_name }' already exists.")
|
66
|
+
else
|
67
|
+
run_command(['flynn', 'create', "--remote=#{ cluster_name }", '-y', 'project_name'])
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
def deploy
|
73
|
+
run_command(['git', 'push', cluster_name, 'HEAD:refs/heads/master'])
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
def domain_for_cluster
|
78
|
+
ENV["FLYNN_#{ current_branch }_DOMAIN"]
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
def domain_for_web_host
|
83
|
+
"#{ current_branch.downcase }.#{ hosting_namespace }"
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
def hosting_namespace
|
88
|
+
if ENV['SATORIX_HOSTING_NAMESPACE'].to_s !~ only_whitespace
|
89
|
+
ENV['SATORIX_HOSTING_NAMESPACE']
|
90
|
+
else
|
91
|
+
log_error_and_abort("Satorix configuration error: Missing SATORIX_HOSTING_NAMESPACE.\n\nPlease contact support.\n")
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def key
|
98
|
+
ENV["FLYNN_#{ current_branch }_KEY"]
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
def project_exists?
|
103
|
+
run_command(%w[flynn apps], quiet: true).split(/\R/).map { |a| a.split.last }.include? project_name
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
def run_database_migrations?
|
108
|
+
[rails_app?, django_app?].any?
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
def run_database_migrations
|
113
|
+
if desired_resource_provider_names.nil? || desired_resource_provider_names.empty?
|
114
|
+
log 'Skipping migrations, no database has been defined. Please see the resources section of this log for more information.'
|
115
|
+
else
|
116
|
+
run_command(%w[flynn run --enable-log bundle exec rake db:migrate]) if rails_app?
|
117
|
+
run_command(%w[flynn run --enable-log python public/manage.py migrate]) if django_app?
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
def tls_pin
|
123
|
+
ENV["FLYNN_#{ current_branch }_TLSPIN"]
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Satorix
|
4
|
+
module CI
|
5
|
+
module Deploy
|
6
|
+
module Flynn
|
7
|
+
module EnvironmentVariables
|
8
|
+
|
9
|
+
def adjust_env_vars
|
10
|
+
ensure_required_env_vars_are_defined unless ENV["SATORIX_#{ current_branch }_ENFORCE_ENV_VAR_DEFINITION"] == 'false'
|
11
|
+
env_unset
|
12
|
+
env_set
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def aeev_key_exists?
|
17
|
+
!(run_command(%w[flynn env], quiet: true) =~ /#{ exported_aeevs_key }=/mi).nil?
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def aeev_prefix
|
22
|
+
# AEEV - Application Exportable Environment Variable
|
23
|
+
"AEEV_#{ current_branch }_"
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def ci_provided_env_vars
|
28
|
+
{}.tap do |vars|
|
29
|
+
ENV.each do |key, value|
|
30
|
+
vars[key.sub(aeev_prefix, '')] = value.sub('***EMPTY_STRING***', '') if key.start_with?(aeev_prefix)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def current_flynn_keys
|
37
|
+
aeev_key_exists? ? run_command(['flynn', 'env', 'get', exported_aeevs_key], quiet: true).split : []
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def desired_env_vars
|
42
|
+
ci_provided_env_vars.tap do |vars|
|
43
|
+
vars[exported_aeevs_key] = (vars.keys << exported_aeevs_key).sort.join("\n")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def ensure_required_env_vars_are_defined(configuration_file: 'config/secrets.yml')
|
49
|
+
# TODO : handle new Rails secrets methods, like encrypted secrets
|
50
|
+
if File.file?(configuration_file)
|
51
|
+
secrets = YAML.load_file(configuration_file)
|
52
|
+
|
53
|
+
all_secrets = {}
|
54
|
+
all_secrets.merge!(secrets['shared']) if secrets['shared']
|
55
|
+
all_secrets.merge!(secrets['production']) if secrets['production']
|
56
|
+
|
57
|
+
required = all_secrets.to_yaml.scan(/ENV\[['"](?<var>[A-Z0-9_.]+)['"]\]/).flatten.uniq
|
58
|
+
set = ci_provided_env_vars.keys
|
59
|
+
|
60
|
+
missing = required - set
|
61
|
+
|
62
|
+
if missing.empty?
|
63
|
+
log "All required environment variables from #{ configuration_file } have been defined."
|
64
|
+
else
|
65
|
+
log_error "Environment variables specified in #{ configuration_file } were not defined for the #{ current_branch.downcase } branch."
|
66
|
+
log_error "\nPlease define the following variables in your dashboard:\n#{ missing.join("\n") }\n"
|
67
|
+
log_error_and_abort 'Missing required environment variables.'
|
68
|
+
end
|
69
|
+
else
|
70
|
+
log "No #{ configuration_file } exists, skipping environment variable enforcement."
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
def env_set
|
76
|
+
if env_vars_to_set.empty?
|
77
|
+
log 'No new environment variables to set.'
|
78
|
+
else
|
79
|
+
keys_and_values = env_vars_to_set.map { |k, v| "#{ k }=#{ v }" }
|
80
|
+
run_command(['flynn', 'env', 'set', keys_and_values].flatten, filtered_text: env_vars_to_set.values)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
def env_unset
|
86
|
+
if env_vars_to_unset.empty?
|
87
|
+
log 'No existing environment variables to unset.'
|
88
|
+
else
|
89
|
+
run_command(['flynn', 'env', 'unset', env_vars_to_unset])
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
def env_vars
|
95
|
+
@_env_vars ||= begin
|
96
|
+
{}.tap do |vars|
|
97
|
+
current_flynn_keys.each { |key| vars[key] = run_command(['flynn', 'env', 'get', key], quiet: true).chomp }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
def env_vars_to_set
|
104
|
+
@_env_vars_to_set ||= desired_env_vars.reject { |k, v| env_vars.key?(k) && env_vars[k] == v }
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
def env_vars_to_unset
|
109
|
+
@_env_vars_to_unset ||= env_vars.keys - desired_env_vars.keys
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
def exported_aeevs_key
|
114
|
+
'AEEV_KEYS'
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Satorix
|
2
|
+
module CI
|
3
|
+
module Deploy
|
4
|
+
module Flynn
|
5
|
+
module Resources
|
6
|
+
|
7
|
+
def add_resources
|
8
|
+
if resources_to_add.empty?
|
9
|
+
log 'No resources to add.'
|
10
|
+
else
|
11
|
+
resources_to_add.each { |resource| run_command(['flynn', 'resource', 'add', resource]) }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def available_resources
|
17
|
+
%w(postgres mysql mongodb redis)
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def current_resource_provider_names
|
22
|
+
resource.split("\n").drop(1).map(&:split).map(&:last)
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def desired_resource_provider_names
|
27
|
+
names = ENV[resource_provider_key].to_s.split
|
28
|
+
disallowed = names - available_resources
|
29
|
+
unless disallowed.empty?
|
30
|
+
log_error_and_abort("Invalid resource#{ 's' if disallowed.length > 1 }: #{ disallowed.join(' ') }")
|
31
|
+
end
|
32
|
+
names
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def remove_resources
|
37
|
+
if resources_to_remove.empty?
|
38
|
+
log 'No resources to remove.'
|
39
|
+
else
|
40
|
+
log "The following previously allocated resources are no longer defined in #{ resource_provider_key }:"
|
41
|
+
log resources_to_remove.join(' ')
|
42
|
+
log ''
|
43
|
+
log 'To remove them, use the flynn resource command: https://flynn.io/docs/cli#resource'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def resource
|
49
|
+
run_command(%w[flynn resource], quiet: true).chomp
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def resource_provider_key
|
54
|
+
"FLYNN_#{ current_branch }_RESOURCES"
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def resources_to_add
|
59
|
+
desired_resource_provider_names - current_resource_provider_names
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def resources_to_remove
|
64
|
+
current_resource_provider_names - desired_resource_provider_names
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def set_resources
|
69
|
+
add_resources
|
70
|
+
remove_resources
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,266 @@
|
|
1
|
+
module Satorix
|
2
|
+
module CI
|
3
|
+
module Deploy
|
4
|
+
module Flynn
|
5
|
+
module Routes
|
6
|
+
|
7
|
+
def find_or_create_route(domain)
|
8
|
+
route_ids = route_ids(domain)
|
9
|
+
if route_ids.empty?
|
10
|
+
log "Adding route for #{ domain }..."
|
11
|
+
route_ids << fc_route_add(domain)
|
12
|
+
log "Route for #{ domain } added with the ID of #{ route_ids.first }."
|
13
|
+
else
|
14
|
+
multiple = route_ids.length > 1
|
15
|
+
log "Route#{ 's' if multiple } already exist#{ 's' unless multiple } for #{ domain }."
|
16
|
+
end
|
17
|
+
|
18
|
+
route_ids
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def configure_routes
|
23
|
+
defined_and_internal_routes.each do |ddev_id, domain|
|
24
|
+
route_ids = find_or_create_route(domain)
|
25
|
+
route_ids.each do |route_id|
|
26
|
+
add_tls_to_route(route_id: route_id, ddev_id: ddev_id)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def add_tls_to_route(route_id:, ddev_id:)
|
33
|
+
domain = defined_and_internal_routes[ddev_id]
|
34
|
+
if use_tls?(ddev_id)
|
35
|
+
if use_lets_encrypt?(ddev_id)
|
36
|
+
log "Using Let's Encrypt for #{ domain }."
|
37
|
+
log_error_and_abort "Let's Encrypt support is not implemented, yet!"
|
38
|
+
else
|
39
|
+
log "Using #{ user_defined_tls?(ddev_id) ? 'custom' : 'default' } certificate details for #{ domain } (#{ service_for_route_id(route_id) } service)."
|
40
|
+
File.open('crt', 'w') { |f| f.write(crt_for_ddev_id(ddev_id)) }
|
41
|
+
File.open('key', 'w') { |f| f.write(key_for_ddev_id(ddev_id)) }
|
42
|
+
fc_route_update(route_id)
|
43
|
+
end
|
44
|
+
else
|
45
|
+
log "Skipping TLS configuration for #{ domain }."
|
46
|
+
log "Environment variables #{ env_var_crt_prefix }#{ ddev_id } and #{ env_var_key_prefix }#{ ddev_id } have not been specified."
|
47
|
+
log 'For more information, please refer to https://www.satorix.com/docs/user/projects#certificates'
|
48
|
+
end
|
49
|
+
log ''
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def canonical_domain
|
54
|
+
ENV["AEEV_#{ current_branch }_SATORIX_CANONICAL_URI_HOST"]
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def canonical_domain_information
|
59
|
+
"\nThe above routes will all be redirected to the default URL:\n\n\t#{ canonical_uri }\n\n" if canonical_uri?
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def canonical_domain_protocol
|
64
|
+
ENV["AEEV_#{ current_branch }_SATORIX_CANONICAL_URI_PROTOCOL"]
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def canonical_uri
|
69
|
+
"#{ canonical_domain_protocol }://#{ canonical_domain }" if canonical_uri?
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def canonical_uri?
|
74
|
+
[canonical_domain, canonical_domain_protocol].all? { |x| x.to_s !~ only_whitespace }
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
def crt_for_ddev_id(ddev_id)
|
79
|
+
ENV["#{ env_var_crt_prefix }#{ user_defined_tls?(ddev_id) ? ddev_id : 'DEFAULT' }"]
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
def custom_crt_for_ddev_id?(ddev_id)
|
84
|
+
ENV["#{ env_var_crt_prefix }#{ ddev_id }"].to_s !~ only_whitespace
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
def custom_key_for_ddev_id?(ddev_id)
|
89
|
+
ENV["#{ env_var_key_prefix }#{ ddev_id }"].to_s !~ only_whitespace
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
def defined_and_internal_routes
|
94
|
+
defined_routes.merge flynn_internal_routes
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
def defined_routes
|
99
|
+
{}.tap do |routes|
|
100
|
+
invalid_keys = flynn_internal_routes.keys
|
101
|
+
ENV.each do |key, value|
|
102
|
+
next unless key.start_with?(env_var_domain_prefix)
|
103
|
+
renamed_key = key.sub(env_var_domain_prefix, '')
|
104
|
+
message = "The user-defined route #{ key } conflicts with an internal route."
|
105
|
+
log_error_and_abort message if invalid_keys.include?(renamed_key)
|
106
|
+
routes[renamed_key] = value
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
def display_routing_information
|
113
|
+
log 'All application routes...'
|
114
|
+
log ''
|
115
|
+
log urlified_routes_for_display.map { |r| "\t#{ r }" }
|
116
|
+
log canonical_domain_information if canonical_uri?
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
def env_var_crt_prefix
|
121
|
+
"CRT_#{ current_branch }_"
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
def env_var_domain_prefix
|
126
|
+
"DDEV_#{ current_branch }_"
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
def env_var_key_prefix
|
131
|
+
"KEY_#{ current_branch }_"
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
def fc_route
|
136
|
+
run_command(['flynn', '-a', project_name, 'route'], quiet: true).chomp
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
def fc_route_add(domain)
|
141
|
+
run_command(['flynn', 'route', 'add', 'http', domain, '--sticky']).chomp
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
def fc_route_remove(route_id)
|
146
|
+
run_command(['flynn', 'route', 'remove', route_id])
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
def fc_route_update(route_id)
|
151
|
+
run_command(['flynn', 'route', 'update', route_id, '--tls-cert=crt', '--tls-key=key', '--sticky'], quiet: true)
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
def flynn_internal_routes
|
156
|
+
{ 'FLYNN_INTERNAL' => "#{ project_name }.#{ domain_for_web_host }" }
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
def key_for_ddev_id(ddev_id)
|
161
|
+
ENV["#{ env_var_key_prefix }#{ user_defined_tls?(ddev_id) ? ddev_id : 'DEFAULT' }"]
|
162
|
+
end
|
163
|
+
|
164
|
+
|
165
|
+
def only_whitespace
|
166
|
+
/\A\s*\z/m
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
def remove_undefined_routes
|
171
|
+
routes_to_remove.each do |route|
|
172
|
+
log_header "Removing undefined route #{ route[routes_legend['ROUTE']] }..."
|
173
|
+
fc_route_remove route[routes_legend['ID']]
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
def route_ids(route)
|
179
|
+
[].tap do |route_ids|
|
180
|
+
routes_all_of('ROUTE').map { |r| r.sub(/https??:/i, '') }.each_with_index do |r, i|
|
181
|
+
route_ids << routes_all_of('ID')[i] if r == route
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
def routes
|
188
|
+
routes_with_legend.drop(1)
|
189
|
+
end
|
190
|
+
|
191
|
+
|
192
|
+
def routes_all_of(field)
|
193
|
+
routes.map { |a| a[routes_legend[field]] }
|
194
|
+
end
|
195
|
+
|
196
|
+
|
197
|
+
def routes_legend
|
198
|
+
{}.tap { |h| routes_with_legend.first.each_with_index { |route, index| h[route] = index } }
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
def routes_to_remove
|
203
|
+
routes.reject do |route|
|
204
|
+
defined_and_internal_routes.values.include? route[routes_legend['ROUTE']].partition(':').last
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
def routes_with_legend
|
210
|
+
fc_route.split("\n").map(&:split)
|
211
|
+
end
|
212
|
+
|
213
|
+
|
214
|
+
def service_for_route_id(route_id)
|
215
|
+
index = routes_all_of('ID').index(route_id)
|
216
|
+
routes_all_of('SERVICE')[index]
|
217
|
+
end
|
218
|
+
|
219
|
+
|
220
|
+
def setup_routes
|
221
|
+
configure_routes
|
222
|
+
remove_undefined_routes
|
223
|
+
display_routing_information
|
224
|
+
end
|
225
|
+
|
226
|
+
|
227
|
+
def urlified_routes
|
228
|
+
routes_all_of('ROUTE').map { |r| urlify_route r }
|
229
|
+
end
|
230
|
+
|
231
|
+
|
232
|
+
def urlified_routes_for_display
|
233
|
+
urlified_routes.map { |route| urlify_route_for_display route }.sort
|
234
|
+
end
|
235
|
+
|
236
|
+
|
237
|
+
def urlify_route(route)
|
238
|
+
route.sub(':', '://')
|
239
|
+
end
|
240
|
+
|
241
|
+
|
242
|
+
def urlify_route_for_display(route)
|
243
|
+
route =~ /^http:/ ? route : "#{ route.sub 'https', 'http' }, #{ route }"
|
244
|
+
end
|
245
|
+
|
246
|
+
|
247
|
+
def use_lets_encrypt?(ddev_id)
|
248
|
+
crt_for_ddev_id(ddev_id).to_s.gsub(/\W+/, '').casecmp('letsencrypt').zero? &&
|
249
|
+
key_for_ddev_id(ddev_id).to_s.gsub(/\W+/, '').casecmp('letsencrypt').zero?
|
250
|
+
end
|
251
|
+
|
252
|
+
|
253
|
+
def use_tls?(ddev_id)
|
254
|
+
[crt_for_ddev_id(ddev_id), key_for_ddev_id(ddev_id)].all? { |x| x.to_s !~ only_whitespace }
|
255
|
+
end
|
256
|
+
|
257
|
+
|
258
|
+
def user_defined_tls?(ddev_id)
|
259
|
+
custom_crt_for_ddev_id?(ddev_id) && custom_key_for_ddev_id?(ddev_id)
|
260
|
+
end
|
261
|
+
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|