orchestration 0.3.17 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/LICENSE +7 -0
- data/MANIFEST +76 -0
- data/Makefile +3 -3
- data/README.md +162 -137
- data/Rakefile +2 -2
- data/config/locales/en.yml +3 -1
- data/lib/orchestration/docker_compose/app_service.rb +84 -13
- data/lib/orchestration/docker_compose/compose_configuration.rb +69 -0
- data/lib/orchestration/docker_compose/database_service.rb +15 -13
- data/lib/orchestration/docker_compose/install_generator.rb +3 -2
- data/lib/orchestration/docker_compose/mongo_service.rb +5 -5
- data/lib/orchestration/docker_compose/rabbitmq_service.rb +2 -3
- data/lib/orchestration/docker_compose.rb +1 -0
- data/lib/orchestration/environment.rb +19 -6
- data/lib/orchestration/errors.rb +1 -1
- data/lib/orchestration/file_helpers.rb +27 -4
- data/lib/orchestration/install_generator.rb +85 -20
- data/lib/orchestration/services/app/configuration.rb +9 -5
- data/lib/orchestration/services/app/healthcheck.rb +1 -22
- data/lib/orchestration/services/database/adapters/mysql2.rb +13 -2
- data/lib/orchestration/services/database/adapters/postgresql.rb +0 -1
- data/lib/orchestration/services/database/configuration.rb +68 -75
- data/lib/orchestration/services/database/healthcheck.rb +10 -1
- data/lib/orchestration/services/listener/configuration.rb +1 -1
- data/lib/orchestration/services/listener/healthcheck.rb +2 -2
- data/lib/orchestration/services/{configuration_base.rb → mixins/configuration_base.rb} +15 -13
- data/lib/orchestration/services/{healthcheck_base.rb → mixins/healthcheck_base.rb} +3 -2
- data/lib/orchestration/services/mixins/http_healthcheck.rb +38 -0
- data/lib/orchestration/services/mongo/configuration.rb +37 -63
- data/lib/orchestration/services/mongo/healthcheck.rb +3 -32
- data/lib/orchestration/services/rabbitmq/configuration.rb +11 -22
- data/lib/orchestration/services/rabbitmq/healthcheck.rb +2 -2
- data/lib/orchestration/services.rb +3 -2
- data/lib/orchestration/templates/Dockerfile.erb +8 -4
- data/lib/orchestration/templates/database.yml.erb +32 -0
- data/lib/orchestration/templates/deploy.mk.erb +2 -2
- data/lib/orchestration/templates/entrypoint.sh.erb +13 -4
- data/lib/orchestration/templates/env.erb +10 -2
- data/lib/orchestration/templates/healthcheck.rb.erb +56 -0
- data/lib/orchestration/templates/makefile_macros.mk.erb +108 -0
- data/lib/orchestration/templates/mongoid.yml.erb +18 -0
- data/lib/orchestration/templates/orchestration.mk.erb +242 -120
- data/lib/orchestration/templates/puma.rb.erb +19 -0
- data/lib/orchestration/templates/rabbitmq.yml.erb +12 -0
- data/lib/orchestration/templates/unicorn.rb.erb +5 -5
- data/lib/orchestration/terminal.rb +13 -15
- data/lib/orchestration/version.rb +1 -1
- data/lib/orchestration.rb +20 -2
- data/lib/tasks/orchestration.rake +3 -1
- data/orchestration.gemspec +3 -5
- metadata +23 -13
@@ -8,41 +8,112 @@ module Orchestration
|
|
8
8
|
@config = config
|
9
9
|
end
|
10
10
|
|
11
|
+
class << self
|
12
|
+
def command
|
13
|
+
server = env.web_server
|
14
|
+
%w[bundle exec] + case env.web_server
|
15
|
+
when 'puma'
|
16
|
+
%w[puma -C config/puma.rb]
|
17
|
+
when 'unicorn'
|
18
|
+
%w[unicorn -c config/unicorn.rb]
|
19
|
+
else
|
20
|
+
unsupported_web_server(server)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def entrypoint
|
25
|
+
["/app/#{orchestration}/entrypoint.sh"]
|
26
|
+
end
|
27
|
+
|
28
|
+
def healthcheck
|
29
|
+
{
|
30
|
+
'test' => ['ruby', "/app/#{orchestration}/healthcheck.rb"],
|
31
|
+
# Defaults according to
|
32
|
+
# https://docs.docker.com/engine/reference/builder/#healthcheck
|
33
|
+
# Except start_period which cannot be set to 0s
|
34
|
+
'interval' => '30s',
|
35
|
+
'timeout' => '30s',
|
36
|
+
'start_period' => '5s',
|
37
|
+
'retries' => 3
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def orchestration
|
44
|
+
env.orchestration_dir_name
|
45
|
+
end
|
46
|
+
|
47
|
+
def env
|
48
|
+
@env ||= Environment.new
|
49
|
+
end
|
50
|
+
|
51
|
+
def unsupported_web_server(server)
|
52
|
+
raise ArgumentError,
|
53
|
+
I18n.t(
|
54
|
+
'orchestration.rake.app.unspported_web_server',
|
55
|
+
server: server,
|
56
|
+
expected: %w[puma unicorn]
|
57
|
+
)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
11
61
|
def definition
|
12
62
|
{
|
13
63
|
'image' => image,
|
14
64
|
'environment' => environment,
|
15
|
-
'ports' => ports
|
65
|
+
'ports' => ports,
|
66
|
+
'deploy' => deploy,
|
67
|
+
'logging' => logging
|
16
68
|
}
|
17
69
|
end
|
18
70
|
|
19
71
|
private
|
20
72
|
|
21
73
|
def image
|
22
|
-
'${DOCKER_ORGANIZATION}/${DOCKER_REPOSITORY}'
|
74
|
+
'${DOCKER_ORGANIZATION}/${DOCKER_REPOSITORY}:${DOCKER_TAG}'
|
75
|
+
end
|
76
|
+
|
77
|
+
def deploy
|
78
|
+
{
|
79
|
+
'mode' => 'replicated',
|
80
|
+
'replicas' => '${REPLICAS}'
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
def logging
|
85
|
+
{
|
86
|
+
'driver' => 'json-file',
|
87
|
+
'options' => {
|
88
|
+
'max-size' => '10m',
|
89
|
+
'max-file' => '5'
|
90
|
+
}
|
91
|
+
}
|
23
92
|
end
|
24
93
|
|
25
94
|
def environment
|
26
95
|
{
|
27
96
|
'RAILS_LOG_TO_STDOUT' => '1',
|
28
97
|
'RAILS_SERVE_STATIC_FILES' => '1',
|
29
|
-
'
|
30
|
-
'
|
31
|
-
|
32
|
-
}.merge(inherited_environment)
|
98
|
+
'WEB_PRELOAD_APP' => '1',
|
99
|
+
'WEB_HEALTHCHECK_PATH' => '/'
|
100
|
+
}.merge(Hash[inherited_environment.map { |key| [key, nil] }])
|
33
101
|
end
|
34
102
|
|
35
103
|
def inherited_environment
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
104
|
+
%w[
|
105
|
+
DATABASE_URL
|
106
|
+
HOST_UID
|
107
|
+
RAILS_ENV
|
108
|
+
SECRET_KEY_BASE
|
109
|
+
WEB_CONCURRENCY
|
110
|
+
WEB_TIMEOUT
|
111
|
+
WEB_WORKER_PROCESSES
|
112
|
+
]
|
42
113
|
end
|
43
114
|
|
44
115
|
def ports
|
45
|
-
['${
|
116
|
+
['${CONTAINER_PORT:?CONTAINER_PORT must be provided}:8080']
|
46
117
|
end
|
47
118
|
end
|
48
119
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orchestration
|
4
|
+
module DockerCompose
|
5
|
+
class ComposeConfiguration
|
6
|
+
def initialize(env)
|
7
|
+
@env = env
|
8
|
+
end
|
9
|
+
|
10
|
+
def services
|
11
|
+
config['services']
|
12
|
+
end
|
13
|
+
|
14
|
+
def database_adapter_name
|
15
|
+
return nil unless defined?(ActiveRecord)
|
16
|
+
return 'postgresql' if defined?(::PG)
|
17
|
+
return 'mysql2' if defined?(::Mysql2)
|
18
|
+
return 'sqlite3' if defined?(::SQLite3)
|
19
|
+
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def database_adapter
|
24
|
+
return nil unless defined?(ActiveRecord)
|
25
|
+
|
26
|
+
base = Orchestration::Services::Database::Adapters
|
27
|
+
return base::Postgresql.new if defined?(::PG)
|
28
|
+
return base::Mysql2.new if defined?(::Mysql2)
|
29
|
+
return base::Sqlite3.new if defined?(::SQLite3)
|
30
|
+
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def local_port(name, remote_port = nil)
|
35
|
+
return nil if ports(name).empty?
|
36
|
+
return ports(name).first[:local].to_i if remote_port.nil?
|
37
|
+
|
38
|
+
ports(name).find { |mapping| mapping[:remote] == remote_port }
|
39
|
+
.fetch(:local)
|
40
|
+
.to_i
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def config
|
46
|
+
@config ||= @env.docker_compose_config
|
47
|
+
end
|
48
|
+
|
49
|
+
def ports(name)
|
50
|
+
services
|
51
|
+
.fetch(name.to_s)
|
52
|
+
.fetch('ports', [])
|
53
|
+
.map do |mapping|
|
54
|
+
next short_format_ports(mapping) if mapping.is_a?(String)
|
55
|
+
|
56
|
+
{
|
57
|
+
local: mapping.fetch('published'),
|
58
|
+
remote: mapping.fetch('target')
|
59
|
+
}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def short_format_ports(mapping)
|
64
|
+
local, _, remote = mapping.partition(':')
|
65
|
+
{ local: local, remote: remote }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -3,41 +3,43 @@
|
|
3
3
|
module Orchestration
|
4
4
|
module DockerCompose
|
5
5
|
class DatabaseService
|
6
|
-
# We dictate which port all database services will run on in their
|
7
|
-
# container to simplify port mapping.
|
8
|
-
PORT = 3354
|
9
|
-
|
10
6
|
def initialize(config, environment)
|
11
7
|
@environment = environment
|
12
8
|
@config = config
|
13
9
|
end
|
14
10
|
|
15
11
|
def definition
|
16
|
-
return nil
|
17
|
-
return nil if
|
12
|
+
return nil unless @config.enabled?
|
13
|
+
return nil if adapter.name == 'sqlite3'
|
18
14
|
|
19
15
|
{
|
20
|
-
'image' =>
|
21
|
-
'environment' =>
|
16
|
+
'image' => adapter.image,
|
17
|
+
'environment' => adapter.environment
|
22
18
|
}.merge(ports).merge(volumes)
|
23
19
|
end
|
24
20
|
|
25
21
|
private
|
26
22
|
|
27
|
-
def
|
28
|
-
@
|
23
|
+
def adapter
|
24
|
+
name = ComposeConfiguration.new(@environment).database_adapter_name
|
25
|
+
base = 'Orchestration::Services::Database::Adapters'
|
26
|
+
Object.const_get("#{base}::#{name.capitalize}").new
|
27
|
+
end
|
28
|
+
|
29
|
+
def remote_port
|
30
|
+
adapter.default_port
|
29
31
|
end
|
30
32
|
|
31
33
|
def ports
|
32
34
|
return {} unless %i[development test].include?(@environment)
|
33
35
|
|
34
|
-
{ 'ports' => ["#{
|
36
|
+
{ 'ports' => ["#{Orchestration.random_local_port}:#{remote_port}"] }
|
35
37
|
end
|
36
38
|
|
37
39
|
def volumes
|
38
|
-
return {}
|
40
|
+
return {} if @environment == :test
|
39
41
|
|
40
|
-
{ 'volumes' => ["#{
|
42
|
+
{ 'volumes' => ["#{@config.env.database_volume}:#{adapter.data_dir}"] }
|
41
43
|
end
|
42
44
|
end
|
43
45
|
end
|
@@ -56,7 +56,8 @@ module Orchestration
|
|
56
56
|
def structure(environment = nil)
|
57
57
|
{
|
58
58
|
'version' => compose_config(environment).version,
|
59
|
-
'services' => services(environment)
|
59
|
+
'services' => services(environment),
|
60
|
+
'volumes' => volumes(environment)
|
60
61
|
}
|
61
62
|
end
|
62
63
|
|
@@ -107,7 +108,7 @@ module Orchestration
|
|
107
108
|
end
|
108
109
|
|
109
110
|
def service_enabled?(service_name)
|
110
|
-
return false
|
111
|
+
return false unless configuration(service_name).enabled?
|
111
112
|
|
112
113
|
true
|
113
114
|
end
|
@@ -11,7 +11,7 @@ module Orchestration
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def definition
|
14
|
-
return nil
|
14
|
+
return nil unless @config.enabled?
|
15
15
|
|
16
16
|
{ 'image' => 'library/mongo' }.merge(ports).merge(volumes)
|
17
17
|
end
|
@@ -30,16 +30,16 @@ module Orchestration
|
|
30
30
|
{ 'volumes' => ["#{@config.env.mongo_volume}:/data/db"] }
|
31
31
|
end
|
32
32
|
|
33
|
-
def local_port
|
34
|
-
@config.port.nil? ? remote_port : @config.port
|
35
|
-
end
|
36
|
-
|
37
33
|
def client
|
38
34
|
Services::Mong::Configuration::CONFIG_KEYS.each do |key|
|
39
35
|
return @config.settings.fetch(key) if @config.settings.key?(key)
|
40
36
|
end
|
41
37
|
end
|
42
38
|
|
39
|
+
def local_port
|
40
|
+
Orchestration.random_local_port
|
41
|
+
end
|
42
|
+
|
43
43
|
def remote_port
|
44
44
|
Orchestration::Services::Mongo::PORT
|
45
45
|
end
|
@@ -9,7 +9,7 @@ module Orchestration
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def definition
|
12
|
-
return nil
|
12
|
+
return nil unless @config.enabled?
|
13
13
|
|
14
14
|
{ 'image' => 'library/rabbitmq' }.merge(ports)
|
15
15
|
end
|
@@ -17,10 +17,9 @@ module Orchestration
|
|
17
17
|
def ports
|
18
18
|
return {} unless %i[development test].include?(@environment)
|
19
19
|
|
20
|
-
host_port = @config.settings.fetch('port', 5672)
|
21
20
|
container_port = Orchestration::Services::RabbitMQ::PORT
|
22
21
|
|
23
|
-
{ 'ports' => ["#{
|
22
|
+
{ 'ports' => ["#{Orchestration.random_local_port}:#{container_port}"] }
|
24
23
|
end
|
25
24
|
end
|
26
25
|
end
|
@@ -7,6 +7,7 @@ end
|
|
7
7
|
|
8
8
|
require 'orchestration/docker_compose/install_generator'
|
9
9
|
require 'orchestration/docker_compose/configuration'
|
10
|
+
require 'orchestration/docker_compose/compose_configuration'
|
10
11
|
|
11
12
|
require 'orchestration/docker_compose/app_service'
|
12
13
|
require 'orchestration/docker_compose/database_service'
|
@@ -12,10 +12,19 @@ module Orchestration
|
|
12
12
|
ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
|
13
13
|
end
|
14
14
|
|
15
|
+
def web_server
|
16
|
+
# Used at installation time only
|
17
|
+
ENV.fetch('server', 'puma')
|
18
|
+
end
|
19
|
+
|
15
20
|
def database_url
|
16
21
|
ENV['DATABASE_URL']
|
17
22
|
end
|
18
23
|
|
24
|
+
def mongo_url
|
25
|
+
ENV['MONGO_URL']
|
26
|
+
end
|
27
|
+
|
19
28
|
def mongoid_configuration_path
|
20
29
|
root.join('config', 'mongoid.yml')
|
21
30
|
end
|
@@ -61,6 +70,14 @@ module Orchestration
|
|
61
70
|
Rails.application.class.parent.name.underscore
|
62
71
|
end
|
63
72
|
|
73
|
+
def rabbitmq_url
|
74
|
+
ENV.fetch('RABBITMQ_URL', nil)
|
75
|
+
end
|
76
|
+
|
77
|
+
def app_port
|
78
|
+
ENV.fetch('CONTAINER_PORT', ENV.fetch('WEB_PORT', '3000')).to_i
|
79
|
+
end
|
80
|
+
|
64
81
|
def app_name
|
65
82
|
settings.get('docker.repository')
|
66
83
|
end
|
@@ -83,16 +100,12 @@ module Orchestration
|
|
83
100
|
'orchestration'
|
84
101
|
end
|
85
102
|
|
86
|
-
def public_volume
|
87
|
-
"#{app_name}_public"
|
88
|
-
end
|
89
|
-
|
90
103
|
def database_volume
|
91
|
-
|
104
|
+
'database'
|
92
105
|
end
|
93
106
|
|
94
107
|
def mongo_volume
|
95
|
-
|
108
|
+
'mongo'
|
96
109
|
end
|
97
110
|
end
|
98
111
|
end
|
data/lib/orchestration/errors.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Orchestration
|
4
4
|
class OrchestrationError < StandardError; end
|
5
5
|
|
6
|
-
class
|
6
|
+
class HTTPConnectionError < OrchestrationError; end
|
7
7
|
class DatabaseConfigurationError < OrchestrationError; end
|
8
8
|
class MongoConfigurationError < OrchestrationError; end
|
9
9
|
|
@@ -30,7 +30,8 @@ module Orchestration
|
|
30
30
|
path.relative_path_from(@env.root).to_s
|
31
31
|
end
|
32
32
|
|
33
|
-
def simple_copy(template_name, dest, options = {})
|
33
|
+
def simple_copy(template_name, dest = nil, options = {})
|
34
|
+
dest ||= @env.orchestration_root.join(template_name)
|
34
35
|
update_file(
|
35
36
|
dest,
|
36
37
|
template(template_name, env: @env),
|
@@ -42,8 +43,10 @@ module Orchestration
|
|
42
43
|
relpath = relative_path(path)
|
43
44
|
overwrite = options.fetch(:overwrite, true)
|
44
45
|
present = File.exist?(path)
|
45
|
-
return @terminal.write(:skip, relpath) if present && !overwrite
|
46
|
+
return @terminal.write(:skip, relpath) if present && !overwrite && !force?
|
46
47
|
|
48
|
+
previous_content = File.read(path) if present
|
49
|
+
backup(path, previous_content) if options.fetch(:backup, false)
|
47
50
|
write_file(path, content)
|
48
51
|
@terminal.write(:create, relative_path(path))
|
49
52
|
end
|
@@ -52,14 +55,29 @@ module Orchestration
|
|
52
55
|
present = File.exist?(path)
|
53
56
|
return create_file(path, content) unless present
|
54
57
|
|
55
|
-
overwrite = options.fetch(:overwrite, true)
|
56
58
|
previous_content = File.read(path) if present
|
57
|
-
if present
|
59
|
+
if skip?(present, content, previous_content, options)
|
58
60
|
return @terminal.write(:skip, relative_path(path))
|
59
61
|
end
|
60
62
|
|
61
63
|
File.write(path, content)
|
62
64
|
@terminal.write(:update, relative_path(path))
|
65
|
+
|
66
|
+
backup(path, previous_content) if options.fetch(:backup, false)
|
67
|
+
end
|
68
|
+
|
69
|
+
def skip?(present, content, previous_content, options)
|
70
|
+
overwrite = options.fetch(:overwrite, true)
|
71
|
+
return false unless present
|
72
|
+
return true unless overwrite || force?
|
73
|
+
|
74
|
+
previous_content == content
|
75
|
+
end
|
76
|
+
|
77
|
+
def backup(path, previous_content)
|
78
|
+
backup_path = Pathname.new("#{path}.bak")
|
79
|
+
File.write(backup_path, previous_content)
|
80
|
+
@terminal.write(:backup, relative_path(backup_path))
|
63
81
|
end
|
64
82
|
|
65
83
|
def append_file(path, content, echo: true)
|
@@ -105,5 +123,10 @@ module Orchestration
|
|
105
123
|
FileUtils.mkdir_p(File.dirname(path))
|
106
124
|
File.write(path, content)
|
107
125
|
end
|
126
|
+
|
127
|
+
def force?
|
128
|
+
# Rake task was invoked with `force=yes`
|
129
|
+
ENV['force'] == 'yes'
|
130
|
+
end
|
108
131
|
end
|
109
132
|
end
|
@@ -4,6 +4,7 @@ require 'thor'
|
|
4
4
|
require 'tempfile'
|
5
5
|
|
6
6
|
module Orchestration
|
7
|
+
# rubocop:disable Metrics/ClassLength
|
7
8
|
class InstallGenerator < Thor::Group
|
8
9
|
include FileHelpers
|
9
10
|
|
@@ -20,7 +21,7 @@ module Orchestration
|
|
20
21
|
@terminal.ask_setting('docker.organization')
|
21
22
|
@terminal.ask_setting('docker.repository', @env.default_app_name)
|
22
23
|
relpath = relative_path(path)
|
23
|
-
return @terminal.write(:create, relpath) unless @settings.exist?
|
24
|
+
return @terminal.write(:create, relpath) unless @settings.exist? || force?
|
24
25
|
return @terminal.write(:update, relpath) if @settings.dirty?
|
25
26
|
|
26
27
|
@terminal.write(:skip, relpath)
|
@@ -39,10 +40,9 @@ module Orchestration
|
|
39
40
|
end
|
40
41
|
|
41
42
|
def dockerfile
|
42
|
-
content = template('Dockerfile', ruby_version: RUBY_VERSION)
|
43
43
|
create_file(
|
44
44
|
orchestration_dir.join('Dockerfile'),
|
45
|
-
|
45
|
+
dockerfile_content,
|
46
46
|
overwrite: false
|
47
47
|
)
|
48
48
|
end
|
@@ -64,14 +64,55 @@ module Orchestration
|
|
64
64
|
ensure_lines_in_file(path, entries)
|
65
65
|
end
|
66
66
|
|
67
|
+
def docker_compose
|
68
|
+
@docker_compose.docker_compose_yml
|
69
|
+
@docker_compose.docker_compose_test_yml
|
70
|
+
@docker_compose.docker_compose_development_yml
|
71
|
+
@docker_compose.docker_compose_local_yml
|
72
|
+
@docker_compose.docker_compose_production_yml
|
73
|
+
@docker_compose.docker_compose_override_yml
|
74
|
+
end
|
75
|
+
|
76
|
+
def puma
|
77
|
+
return nil unless @env.web_server == 'puma'
|
78
|
+
|
79
|
+
content = template('puma.rb')
|
80
|
+
path = @env.root.join('config', 'puma.rb')
|
81
|
+
create_file(path, content, backup: true)
|
82
|
+
end
|
83
|
+
|
67
84
|
def unicorn
|
85
|
+
return nil unless @env.web_server == 'unicorn'
|
86
|
+
|
68
87
|
content = template('unicorn.rb')
|
69
88
|
path = @env.root.join('config', 'unicorn.rb')
|
70
|
-
create_file(path, content,
|
89
|
+
create_file(path, content, backup: true)
|
90
|
+
end
|
91
|
+
|
92
|
+
def database_yml
|
93
|
+
return unless defined?(ActiveRecord)
|
94
|
+
|
95
|
+
service_config('database.yml', Services::Database::Configuration)
|
96
|
+
end
|
97
|
+
|
98
|
+
def mongoid_yml
|
99
|
+
return unless defined?(Mongoid)
|
100
|
+
|
101
|
+
service_config('mongoid.yml', Services::Mongo::Configuration)
|
102
|
+
end
|
103
|
+
|
104
|
+
def rabbitmq_yml
|
105
|
+
return unless defined?(Bunny)
|
106
|
+
|
107
|
+
service_config('rabbitmq.yml', Services::RabbitMQ::Configuration)
|
108
|
+
end
|
109
|
+
|
110
|
+
def healthcheck
|
111
|
+
simple_copy('healthcheck.rb')
|
71
112
|
end
|
72
113
|
|
73
114
|
def yaml_bash
|
74
|
-
simple_copy('yaml.bash'
|
115
|
+
simple_copy('yaml.bash')
|
75
116
|
end
|
76
117
|
|
77
118
|
def env
|
@@ -79,16 +120,7 @@ module Orchestration
|
|
79
120
|
end
|
80
121
|
|
81
122
|
def deploy_mk
|
82
|
-
simple_copy('deploy.mk'
|
83
|
-
end
|
84
|
-
|
85
|
-
def docker_compose
|
86
|
-
@docker_compose.docker_compose_yml
|
87
|
-
@docker_compose.docker_compose_test_yml
|
88
|
-
@docker_compose.docker_compose_development_yml
|
89
|
-
@docker_compose.docker_compose_local_yml
|
90
|
-
@docker_compose.docker_compose_production_yml
|
91
|
-
@docker_compose.docker_compose_override_yml
|
123
|
+
simple_copy('deploy.mk')
|
92
124
|
end
|
93
125
|
|
94
126
|
private
|
@@ -98,15 +130,48 @@ module Orchestration
|
|
98
130
|
end
|
99
131
|
|
100
132
|
def makefile_environment
|
101
|
-
|
133
|
+
macros = template('makefile_macros.mk', env: @env)
|
134
|
+
|
135
|
+
{ env: @env, services: enabled_services, macros: macros }
|
102
136
|
end
|
103
137
|
|
104
|
-
def
|
138
|
+
def enabled_services
|
105
139
|
%i[test development production].map do |environment|
|
106
|
-
@docker_compose.enabled_services(environment)
|
107
|
-
"wait-#{service}"
|
108
|
-
end
|
140
|
+
@docker_compose.enabled_services(environment)
|
109
141
|
end.flatten.uniq
|
110
142
|
end
|
143
|
+
|
144
|
+
def service_config(filename, config_class)
|
145
|
+
content = service_config_content(filename, config_class)
|
146
|
+
path = @env.root.join('config', filename)
|
147
|
+
if path.exist?
|
148
|
+
update_file(path, content, backup: true)
|
149
|
+
else
|
150
|
+
create_file(path, content)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def service_config_content(filename, config_class)
|
155
|
+
template(
|
156
|
+
filename,
|
157
|
+
config: config_class.new(@env),
|
158
|
+
compose: proc do |env|
|
159
|
+
DockerCompose::ComposeConfiguration.new(
|
160
|
+
Environment.new(environment: env)
|
161
|
+
)
|
162
|
+
end
|
163
|
+
)
|
164
|
+
end
|
165
|
+
|
166
|
+
def dockerfile_content
|
167
|
+
template(
|
168
|
+
'Dockerfile',
|
169
|
+
ruby_version: RUBY_VERSION,
|
170
|
+
command: DockerCompose::AppService.command,
|
171
|
+
entrypoint: DockerCompose::AppService.entrypoint,
|
172
|
+
healthcheck: DockerCompose::AppService.healthcheck
|
173
|
+
)
|
174
|
+
end
|
111
175
|
end
|
176
|
+
# rubocop:enable Metrics/ClassLength
|
112
177
|
end
|
@@ -8,6 +8,10 @@ module Orchestration
|
|
8
8
|
|
9
9
|
self.service_name = 'app'
|
10
10
|
|
11
|
+
def enabled?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
11
15
|
def initialize(env, service_name = nil)
|
12
16
|
super
|
13
17
|
@settings = {}
|
@@ -22,7 +26,7 @@ module Orchestration
|
|
22
26
|
end
|
23
27
|
|
24
28
|
def friendly_config
|
25
|
-
"[#{app_name}] #{host}:#{
|
29
|
+
"[#{app_name}] #{host}:#{port}"
|
26
30
|
end
|
27
31
|
|
28
32
|
def database_settings
|
@@ -40,14 +44,14 @@ module Orchestration
|
|
40
44
|
private
|
41
45
|
|
42
46
|
def build_database_url(settings)
|
43
|
-
|
47
|
+
adapter = settings.fetch('adapter')
|
44
48
|
database = settings.fetch('database')
|
45
49
|
username = settings.fetch('username')
|
46
50
|
password = settings.fetch('password')
|
47
|
-
port =
|
48
|
-
host = Database::Configuration.service_name
|
51
|
+
port = settings.fetch('port')
|
52
|
+
host = settings['host'] || Database::Configuration.service_name
|
49
53
|
|
50
|
-
"#{
|
54
|
+
"#{adapter}://#{username}:#{password}@#{host}:#{port}/#{database}"
|
51
55
|
end
|
52
56
|
end
|
53
57
|
end
|
@@ -5,28 +5,7 @@ module Orchestration
|
|
5
5
|
module App
|
6
6
|
class Healthcheck
|
7
7
|
include HealthcheckBase
|
8
|
-
|
9
|
-
def connect
|
10
|
-
response = Net::HTTP.get_response(
|
11
|
-
URI("http://localhost:#{@configuration.local_port}")
|
12
|
-
)
|
13
|
-
connection_error(response.code) if connection_error?(response.code)
|
14
|
-
end
|
15
|
-
|
16
|
-
def connection_errors
|
17
|
-
[Errno::ECONNREFUSED, AppConnectionError]
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def connection_error(code)
|
23
|
-
raise AppConnectionError,
|
24
|
-
I18n.t('orchestration.app.connection_error', code: code)
|
25
|
-
end
|
26
|
-
|
27
|
-
def connection_error?(code)
|
28
|
-
%w[502 503 500].include?(code)
|
29
|
-
end
|
8
|
+
include HTTPHealthcheck
|
30
9
|
end
|
31
10
|
end
|
32
11
|
end
|