orchestration 0.5.11 → 0.6.1
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 +4 -4
- data/README.md +34 -30
- data/config/locales/en.yml +11 -15
- data/lib/orchestration.rb +4 -0
- data/lib/orchestration/docker_compose/app_service.rb +8 -1
- data/lib/orchestration/docker_compose/configuration.rb +1 -1
- data/lib/orchestration/docker_compose/database_service.rb +1 -1
- data/lib/orchestration/docker_compose/install_generator.rb +4 -4
- data/lib/orchestration/docker_compose/rabbitmq_service.rb +4 -2
- data/lib/orchestration/environment.rb +1 -1
- data/lib/orchestration/errors.rb +2 -0
- data/lib/orchestration/install_generator.rb +2 -29
- data/lib/orchestration/make.rb +4 -0
- data/lib/orchestration/make/orchestration.mk +503 -0
- data/lib/orchestration/service_check.rb +24 -38
- data/lib/orchestration/services/database/adapters.rb +1 -0
- data/lib/orchestration/services/database/adapters/adapter_base.rb +21 -0
- data/lib/orchestration/services/database/adapters/mysql2.rb +4 -2
- data/lib/orchestration/services/database/adapters/postgresql.rb +2 -0
- data/lib/orchestration/services/database/adapters/sqlite3.rb +2 -0
- data/lib/orchestration/services/database/configuration.rb +17 -19
- data/lib/orchestration/services/mixins/configuration_base.rb +1 -1
- data/lib/orchestration/services/rabbitmq.rb +1 -0
- data/lib/orchestration/templates/Dockerfile.erb +5 -7
- data/lib/orchestration/templates/application.mk.erb +23 -7
- data/lib/orchestration/templates/rabbitmq.yml.erb +5 -2
- data/lib/orchestration/terminal.rb +4 -3
- data/lib/orchestration/version.rb +1 -1
- data/lib/tasks/orchestration.rake +23 -6
- data/orchestration.gemspec +6 -3
- metadata +64 -21
- data/lib/orchestration/templates/makefile_macros.mk.erb +0 -112
- data/lib/orchestration/templates/orchestration.mk.erb +0 -393
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
module Orchestration
|
4
4
|
class ServiceCheck
|
5
|
-
ATTEMPT_LIMIT = ENV.fetch('ORCHESTRATION_RETRY_LIMIT', '
|
6
|
-
RETRY_INTERVAL = ENV.fetch('ORCHESTRATION_RETRY_INTERVAL', '
|
5
|
+
ATTEMPT_LIMIT = ENV.fetch('ORCHESTRATION_RETRY_LIMIT', '15').to_i
|
6
|
+
RETRY_INTERVAL = ENV.fetch('ORCHESTRATION_RETRY_INTERVAL', '15').to_i
|
7
7
|
|
8
8
|
def initialize(service, terminal, options = {})
|
9
9
|
@service = service
|
@@ -31,36 +31,36 @@ module Orchestration
|
|
31
31
|
@service.connect
|
32
32
|
true
|
33
33
|
rescue *@service.connection_errors => e
|
34
|
-
|
35
|
-
sleep @retry_interval
|
34
|
+
wait_failure(e)
|
36
35
|
retry unless @attempts == @attempt_limit
|
37
36
|
echo_error(e)
|
38
37
|
echo_failure
|
39
38
|
false
|
40
39
|
end
|
41
40
|
|
42
|
-
def
|
43
|
-
@
|
41
|
+
def wait_failure(error)
|
42
|
+
@attempts += 1
|
43
|
+
@last_error = error
|
44
|
+
sleep @retry_interval
|
44
45
|
end
|
45
46
|
|
46
|
-
def
|
47
|
-
@
|
47
|
+
def last_error
|
48
|
+
return nil if @last_error.nil?
|
49
|
+
|
50
|
+
last_error_message
|
48
51
|
end
|
49
52
|
|
50
|
-
def
|
51
|
-
|
52
|
-
"orchestration.#{@service_name}.waiting",
|
53
|
-
config: friendly_config,
|
54
|
-
default: default_waiting
|
55
|
-
)
|
53
|
+
def last_error_message
|
54
|
+
"(#{@last_error&.cause&.class&.name || @last_error&.class&.name})"
|
56
55
|
end
|
57
56
|
|
58
|
-
def
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
57
|
+
def echo_start
|
58
|
+
@terminal.write(@service_name.to_sym, '', :status)
|
59
|
+
@terminal.write(:config, friendly_config)
|
60
|
+
end
|
61
|
+
|
62
|
+
def echo_waiting
|
63
|
+
@terminal.write(:waiting, last_error)
|
64
64
|
end
|
65
65
|
|
66
66
|
def echo_ready
|
@@ -68,30 +68,16 @@ module Orchestration
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def service_ready
|
71
|
-
I18n.t(
|
72
|
-
"orchestration.#{@service_name}.ready",
|
73
|
-
config: friendly_config,
|
74
|
-
default: default_ready
|
75
|
-
)
|
76
|
-
end
|
77
|
-
|
78
|
-
def default_ready
|
79
|
-
I18n.t(
|
80
|
-
'orchestration.custom_service.ready',
|
81
|
-
config: friendly_config,
|
82
|
-
service: @service_name
|
83
|
-
)
|
71
|
+
I18n.t('orchestration.service.ready', service: @service_name)
|
84
72
|
end
|
85
73
|
|
86
74
|
def echo_failure
|
87
|
-
@terminal.write(
|
88
|
-
:failure,
|
89
|
-
I18n.t('orchestration.attempt_limit', limit: @attempt_limit)
|
90
|
-
)
|
75
|
+
@terminal.write(:failure, I18n.t('orchestration.attempt_limit', limit: @attempt_limit))
|
91
76
|
end
|
92
77
|
|
93
78
|
def echo_error(error)
|
94
|
-
|
79
|
+
cause = error.cause.nil? ? error : error.cause
|
80
|
+
@terminal.write(:error, "[#{cause.class.name}] #{cause.message}")
|
95
81
|
end
|
96
82
|
|
97
83
|
def friendly_config
|
@@ -9,6 +9,7 @@ module Orchestration
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
+
require 'orchestration/services/database/adapters/adapter_base'
|
12
13
|
require 'orchestration/services/database/adapters/mysql2'
|
13
14
|
require 'orchestration/services/database/adapters/postgresql'
|
14
15
|
require 'orchestration/services/database/adapters/sqlite3'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orchestration
|
4
|
+
module Services
|
5
|
+
module Database
|
6
|
+
module Adapters
|
7
|
+
module AdapterBase
|
8
|
+
attr_reader :config
|
9
|
+
|
10
|
+
def initialize(config = nil)
|
11
|
+
@config = config
|
12
|
+
end
|
13
|
+
|
14
|
+
def console_command
|
15
|
+
I18n.t("orchestration.dbconsole.#{name}") % config.settings.transform_keys(&:to_sym)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -5,12 +5,14 @@ module Orchestration
|
|
5
5
|
module Database
|
6
6
|
module Adapters
|
7
7
|
class Mysql2
|
8
|
+
include AdapterBase
|
9
|
+
|
8
10
|
def name
|
9
11
|
'mysql2'
|
10
12
|
end
|
11
13
|
|
12
14
|
def image
|
13
|
-
return
|
15
|
+
return mysql57 if gem_version < Gem::Version.new('0.4')
|
14
16
|
|
15
17
|
'library/mysql'
|
16
18
|
end
|
@@ -43,7 +45,7 @@ module Orchestration
|
|
43
45
|
|
44
46
|
private
|
45
47
|
|
46
|
-
def
|
48
|
+
def mysql57
|
47
49
|
'library/mysql:5.7'
|
48
50
|
end
|
49
51
|
|
@@ -15,7 +15,7 @@ module Orchestration
|
|
15
15
|
def friendly_config
|
16
16
|
return "[#{adapter.name}]" if sqlite?
|
17
17
|
|
18
|
-
"[#{adapter.name}] #{host}:#{port}"
|
18
|
+
"[#{adapter.name}] #{adapter.name}://#{username}:#{password}@#{host}:#{port}/#{database}"
|
19
19
|
end
|
20
20
|
|
21
21
|
def settings(healthcheck: false)
|
@@ -33,6 +33,10 @@ module Orchestration
|
|
33
33
|
sqlite? || super
|
34
34
|
end
|
35
35
|
|
36
|
+
def console_command
|
37
|
+
adapter.console_command
|
38
|
+
end
|
39
|
+
|
36
40
|
def adapter
|
37
41
|
url_adapter = url_config['adapter']
|
38
42
|
file_adapter = file_config['adapter']
|
@@ -82,37 +86,31 @@ module Orchestration
|
|
82
86
|
end
|
83
87
|
|
84
88
|
def host
|
85
|
-
|
89
|
+
chained_config('host') || super
|
86
90
|
end
|
87
91
|
|
88
92
|
def port
|
89
93
|
return nil if sqlite?
|
90
94
|
|
91
|
-
|
95
|
+
chained_config('port') || super
|
92
96
|
end
|
93
97
|
|
94
98
|
def username
|
95
|
-
(
|
96
|
-
url_config['username'] ||
|
97
|
-
file_config['username'] ||
|
98
|
-
(adapter && adapter.credentials['username'])
|
99
|
-
)
|
99
|
+
chained_config('username') || (adapter && adapter.credentials['username'])
|
100
100
|
end
|
101
101
|
|
102
102
|
def password
|
103
|
-
(
|
104
|
-
url_config['password'] ||
|
105
|
-
file_config['password'] ||
|
106
|
-
(adapter && adapter.credentials['password'])
|
107
|
-
)
|
103
|
+
chained_config('password') || (adapter && adapter.credentials['password'])
|
108
104
|
end
|
109
105
|
|
110
106
|
def database
|
111
|
-
(
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
107
|
+
chained_config('database') || (adapter && adapter.credentials['database'])
|
108
|
+
end
|
109
|
+
|
110
|
+
def chained_config(key)
|
111
|
+
return url_config[key] || file_config[key] if @env.environment == 'test'
|
112
|
+
|
113
|
+
file_config[key] || url_config[key]
|
116
114
|
end
|
117
115
|
|
118
116
|
def adapter_by_name(name)
|
@@ -121,7 +119,7 @@ module Orchestration
|
|
121
119
|
'mysql' => adapters::Mysql2,
|
122
120
|
'postgresql' => adapters::Postgresql,
|
123
121
|
'sqlite3' => adapters::Sqlite3
|
124
|
-
}.fetch(name).new
|
122
|
+
}.fetch(name).new(self)
|
125
123
|
rescue KeyError
|
126
124
|
Orchestration.error('database.unknown_adapter', adapter: name.inspect)
|
127
125
|
raise
|
@@ -53,7 +53,7 @@ module Orchestration
|
|
53
53
|
local, remote = parse_port(service).map(&:to_i)
|
54
54
|
return remote if @env.environment == 'test' && @options[:sidecar]
|
55
55
|
|
56
|
-
(@env.environment == '
|
56
|
+
(@env.environment == 'deployment' ? remote : local)
|
57
57
|
end
|
58
58
|
|
59
59
|
def service
|
@@ -2,7 +2,7 @@ FROM ruby:<%= ruby_version %>
|
|
2
2
|
ARG BUNDLE_BITBUCKET__ORG
|
3
3
|
ARG BUNDLE_GITHUB__COM
|
4
4
|
ARG GIT_COMMIT
|
5
|
-
RUN curl -sL https://deb.nodesource.com/
|
5
|
+
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - \
|
6
6
|
&& apt-get update \
|
7
7
|
&& DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
8
8
|
nodejs \
|
@@ -13,17 +13,15 @@ RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \
|
|
13
13
|
&& mkdir /app<%if defined?(Webpacker) %> \
|
14
14
|
&& curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash \
|
15
15
|
&& . /root/.bashrc \
|
16
|
-
&& nvm install
|
16
|
+
&& nvm install 14.16.0 \
|
17
17
|
&& npm config set user 0 \
|
18
18
|
&& npm config set unsafe-perm true \
|
19
19
|
&& npm install -g yarn<% end %>
|
20
20
|
WORKDIR /app
|
21
21
|
COPY .build/Gemfile .build/Gemfile.lock ./
|
22
|
-
RUN bundle
|
23
|
-
|
24
|
-
|
25
|
-
RUN . /root/.bashrc ; yarn install
|
26
|
-
<% end %>
|
22
|
+
RUN bundle config set deployment 'true' \
|
23
|
+
&& bundle config set without 'development test' \
|
24
|
+
&& bundle install
|
27
25
|
ADD .build/context.tar .
|
28
26
|
<% if defined?(Webpacker) %>RUN . /root/.bashrc ; NODE_ENV=production RAILS_ENV=production yarn install && NODE_ENV=production RAILS_ENV=production SECRET_KEY_BASE=abc123 bundle exec rake assets:precompile<% elsif Rake::Task.tasks.map(&:name).include?('assets:precompile') %>RUN NODE_ENV=production RAILS_ENV=production SECRET_KEY_BASE=abc123 bundle exec rake assets:precompile<% end %>
|
29
27
|
RUN echo "${GIT_COMMIT}" > /app/GIT_COMMIT
|
@@ -1,20 +1,36 @@
|
|
1
|
+
include $(shell bundle exec ruby -e 'require "orchestration/make"')
|
2
|
+
|
1
3
|
#
|
2
4
|
# Example test command
|
3
5
|
#
|
4
|
-
#
|
6
|
+
# Define your test tasks here. The default command runs RSpec and Rubocop but
|
7
|
+
# you can feel free to add any other tasks you like.
|
5
8
|
#
|
6
|
-
#
|
7
|
-
# waits for them to be ready, and runs DB migrations.
|
9
|
+
# Set up your test dependencies and run tests by calling: `make setup test`
|
8
10
|
#
|
9
|
-
#
|
11
|
+
# Subsequent test runs can skip the setup step and simply run: `make test`
|
10
12
|
#
|
11
13
|
.PHONY: test
|
12
|
-
test:
|
14
|
+
test:
|
13
15
|
bundle exec rspec
|
14
16
|
bundle exec rubocop
|
15
17
|
|
16
|
-
#
|
17
|
-
.
|
18
|
+
#
|
19
|
+
# Define any custom setup that needs to take place before running tests.
|
20
|
+
# If the command exists, it will be called immediately after the `setup`
|
21
|
+
# command (which starts containers and sets up the database).
|
22
|
+
#
|
23
|
+
# This command can be deleted if it is not needed.
|
24
|
+
#
|
25
|
+
.PHONY: post-setup
|
26
|
+
post-setup:
|
27
|
+
@# Setup tasks that are not already provided by Orchestration go here.
|
28
|
+
|
29
|
+
#
|
30
|
+
# Launch all dependencies needed for a development environment and set up the
|
31
|
+
# development database.
|
32
|
+
#
|
33
|
+
.PHONY: setup
|
18
34
|
develop:
|
19
35
|
bundle install
|
20
36
|
@$(MAKE) start env=test
|
@@ -1,12 +1,15 @@
|
|
1
1
|
<% if compose.call('development').services.key?('rabbitmq') %>
|
2
2
|
development:
|
3
|
-
url: <%= "#{'<' + '%' + '='} ENV.fetch('RABBITMQ_URL', 'amqp://127.0.0.1:#{compose.call('development').local_port('rabbitmq')}') #{'%' + '>'}" %>
|
3
|
+
url: <%= "#{'<' + '%' + '='} ENV.fetch('RABBITMQ_URL', 'amqp://127.0.0.1:#{compose.call('development').local_port('rabbitmq', 5672)}') #{'%' + '>'}" %>
|
4
|
+
management_url: <%= "#{'<' + '%' + '='} ENV.fetch('RABBITMQ_MANAGEMENT_URL', 'http://guest:guest@127.0.0.1:#{compose.call('development').local_port('rabbitmq', 15672)}') #{'%' + '>'}" %>
|
4
5
|
<% end %>
|
5
6
|
|
6
7
|
<% if compose.call('test').services.key?('rabbitmq') %>
|
7
8
|
test:
|
8
|
-
url: <%= "#{'<' + '%' + '='} ENV.fetch('RABBITMQ_URL', 'amqp://127.0.0.1:#{compose.call('test').local_port('rabbitmq')}') #{'%' + '>'}" %>
|
9
|
+
url: <%= "#{'<' + '%' + '='} ENV.fetch('RABBITMQ_URL', 'amqp://127.0.0.1:#{compose.call('test').local_port('rabbitmq', 5672)}') #{'%' + '>'}" %>
|
10
|
+
management_url: <%= "#{'<' + '%' + '='} ENV.fetch('RABBITMQ_MANAGEMENT_URL', 'http://guest:guest@127.0.0.1:#{compose.call('test').local_port('rabbitmq', 15672)}') #{'%' + '>'}" %>
|
9
11
|
<% end %>
|
10
12
|
|
11
13
|
production:
|
12
14
|
url: <%%= ENV['RABBITMQ_URL'] %>
|
15
|
+
url: <%%= ENV['RABBITMQ_MANAGEMENT_URL'] %>
|
@@ -4,7 +4,6 @@ module Orchestration
|
|
4
4
|
COLOR_MAP = {
|
5
5
|
failure: %i[red bright],
|
6
6
|
error: %i[red],
|
7
|
-
waiting: %i[yellow],
|
8
7
|
ready: %i[green],
|
9
8
|
create: %i[green],
|
10
9
|
update: %i[yellow],
|
@@ -12,7 +11,9 @@ module Orchestration
|
|
12
11
|
status: %i[blue],
|
13
12
|
setup: %i[blue],
|
14
13
|
input: %i[red],
|
15
|
-
skip: %i[yellow bright]
|
14
|
+
skip: %i[yellow bright],
|
15
|
+
waiting: %i[yellow],
|
16
|
+
config: %i[cyan]
|
16
17
|
}.freeze
|
17
18
|
|
18
19
|
class Terminal
|
@@ -20,7 +21,7 @@ module Orchestration
|
|
20
21
|
@settings = settings
|
21
22
|
end
|
22
23
|
|
23
|
-
def write(desc, message, color_name = nil, newline: true)
|
24
|
+
def write(desc, message = nil, color_name = nil, newline: true)
|
24
25
|
output = newline ? "#{message}\n" : message.to_s
|
25
26
|
$stdout.print colorize(desc, output, color_name)
|
26
27
|
$stdout.flush
|
@@ -8,11 +8,9 @@ namespace :orchestration do
|
|
8
8
|
Orchestration::InstallGenerator.start
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
Orchestration::InstallGenerator.new.orchestration_makefile
|
15
|
-
end
|
11
|
+
desc I18n.t('orchestration.makefile')
|
12
|
+
task :makefile do
|
13
|
+
Orchestration.makefile
|
16
14
|
end
|
17
15
|
|
18
16
|
desc I18n.t('orchestration.rake.config')
|
@@ -21,6 +19,26 @@ namespace :orchestration do
|
|
21
19
|
puts "#{config['docker']['organization']} #{config['docker']['repository']}"
|
22
20
|
end
|
23
21
|
|
22
|
+
namespace :db do
|
23
|
+
desc I18n.t('orchestration.rake.db.url')
|
24
|
+
task :url do
|
25
|
+
config = Rails.application.config_for(:database)
|
26
|
+
|
27
|
+
if config[:adapter] == 'sqlite3'
|
28
|
+
puts "sqlite3:#{config[:database]}"
|
29
|
+
else
|
30
|
+
puts DatabaseUrl.to_active_record_url(config)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
desc I18n.t('orchestration.rake.db.console')
|
35
|
+
task :console do
|
36
|
+
env = Orchestration::Environment.new
|
37
|
+
options = ENV['db'] ? { config_path: "config/database.#{ENV['db']}.yml" } : {}
|
38
|
+
sh Orchestration::Services::Database::Configuration.new(env, nil, options).console_command
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
24
42
|
desc I18n.t('orchestration.rake.healthcheck')
|
25
43
|
task :healthcheck do
|
26
44
|
Orchestration::DockerHealthcheck.execute
|
@@ -28,7 +46,6 @@ namespace :orchestration do
|
|
28
46
|
|
29
47
|
desc I18n.t('orchestration.rake.wait')
|
30
48
|
task :wait do
|
31
|
-
Orchestration::InstallGenerator.new.verify_makefile(skip: false)
|
32
49
|
env = Orchestration::Environment.new
|
33
50
|
services = Orchestration::Services
|
34
51
|
env.docker_compose_config['services'].each do |name, _service|
|