orchestration 0.4.8 → 0.4.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3658b497eae57e7f247ef8f703ddb90ca6c041a2aba5409c61e54291a8e80c22
4
- data.tar.gz: 4a7a242492fd376b62ccb30c2dbf6e5e9163aa202e5fefbbb75b1fef4eab315c
3
+ metadata.gz: 512e1996cb5b673af217cfa7442d7e8e52053de71c86f39babe43986227377a3
4
+ data.tar.gz: cdd316060790c5ab246f33710673417f5bec82fed16d1ea6a88f2232a3283021
5
5
  SHA512:
6
- metadata.gz: d855b7c336167af5db5444f96319de4236d7bb19fdb2ad0554b0c1730485ff57f3d1e3e9d8317138fe60797ac4cf4011bf76f168c1e8948ce3e242e0a012d7c6
7
- data.tar.gz: 98c840d9cdd7272fa2f167373b5df176f9bb0a6d6b22f4be897dd64290f51c17087a20c8f5765e1fdd68890beae7f9de74fdde839441d014d873dfb1effd1996
6
+ metadata.gz: 51e4fc3b1e5931f0089502f71d27c21d3801ee802c23c86e9e8876fd129f838f6f39fa0fd868c05ae22d682132265b16b99023f9ba7b38381ee512c8c5ac1dbc
7
+ data.tar.gz: 3ff522982f74050813537a629aafd15b1dbc45783d47b5ecb44dc17774e856646512d5c9a79fef881b8888e07ffe2987c38b138513804c2c1d953e0d2f291d81
data/README.md CHANGED
@@ -35,7 +35,7 @@ The below screenshot demonstrates _Orchestration_ being installed in a brand new
35
35
  Add _Orchestration_ to your Gemfile:
36
36
 
37
37
  ```ruby
38
- gem 'orchestration', '~> 0.4.8'
38
+ gem 'orchestration', '~> 0.4.9'
39
39
  ```
40
40
 
41
41
  Install:
@@ -199,20 +199,28 @@ Run a production environment locally to simulate your deployment platform:
199
199
  make start env=production
200
200
  ```
201
201
 
202
- ### Deployment to Docker Swarm
202
+ #### Deploy to a remote swarm
203
203
 
204
- To deploy your application to a local _Docker Swarm_ use:
204
+ To connect via _SSH_ to a remote swarm and deploy, pass the `manager` parameter:
205
205
  ```
206
- make deploy
206
+ make deploy manager=user@manager.swarm.example.com
207
207
  ```
208
208
 
209
- #### Deploy to a remote swarm
209
+ #### Roll back a deployment
210
210
 
211
- To connect via _SSH_ to a remote swarm and deploy, pass the `manager` parameter:
211
+ Roll back the `app` service of your stack:
212
212
  ```
213
- make deploy manager=user@manager.swarm.example.com
213
+ make rollback manager=user@manager.swarm.example.com
214
214
  ```
215
215
 
216
+ Roll back a specific service:
217
+ ```
218
+ make rollback manager=user@manager.swarm.example.com service=database
219
+ ```
220
+
221
+ The `project_name` parameter is also supported.
222
+
223
+
216
224
  #### Use a custom stack name
217
225
 
218
226
  The [_Docker_ stack](https://docs.docker.com/engine/reference/commandline/stack/) name defaults to the name of your repository (as defined in `.orchesration.yml`) and the _Rails_ environment, e.g. `anvil_production`.
@@ -355,6 +363,46 @@ Using this approach, the environment variable `RABBITMQ_URL` can be used to conf
355
363
 
356
364
  This is a convention of the _Orchestration_ gem intended to make _RabbitMQ_ configuration consistent with other services.
357
365
 
366
+ ## Alternate Database Configuration Files
367
+
368
+ If you have multiple databases configured in various (e.g.) `config/database.*.yml` files then the `make wait-database` command can be used directly in continuous integration environments to verify that your database services are available.
369
+
370
+ Note that all services from the relevant `docker-compose.yml` configuration will be loaded when using the `make start` or `make test-setup` (called by default `make test` command).
371
+
372
+ Assuming the following configurations:
373
+ ```
374
+ # orchestration/docker-compose.test.yml
375
+ version: '3.7'
376
+ services:
377
+ customdb:
378
+ image: postgres
379
+ ports:
380
+ - "55667:5432"
381
+ # ...
382
+ ```
383
+
384
+ ```
385
+ # config/database.custom.yml
386
+ test:
387
+ adapter: postgresql
388
+ host: 127.0.0.1
389
+ port: 55667
390
+ username: postgres
391
+ password: password
392
+ database: postgres
393
+ ```
394
+
395
+ The following command can be used to ensure that the `customdb` service is available:
396
+ ```
397
+ make wait-database service=custom config=config/database.custom.yml env=test
398
+ ```
399
+
400
+ You may wish to extend the example `Makefile` to include something like this:
401
+ ```
402
+ test: test-setup
403
+ $(MAKE) wait-database service=custom config=config/database.custom.yml env=test
404
+ # ...
405
+ ```
358
406
  ## License
359
407
 
360
408
  [MIT License](LICENSE)
@@ -62,3 +62,4 @@ en:
62
62
  wait: "Wait for RabbitMQ to become available"
63
63
 
64
64
  install: "Install Orchestration tools"
65
+ install_makefile: "(Re)create orchestration/Makefile"
@@ -3,6 +3,15 @@
3
3
  module Orchestration
4
4
  module DockerCompose
5
5
  class ComposeConfiguration
6
+ def self.database_adapter_name
7
+ return nil unless defined?(ActiveRecord)
8
+ return 'postgresql' if defined?(::PG)
9
+ return 'mysql2' if defined?(::Mysql2)
10
+ return 'sqlite3' if defined?(::SQLite3)
11
+
12
+ nil
13
+ end
14
+
6
15
  def initialize(env)
7
16
  @env = env
8
17
  end
@@ -12,12 +21,7 @@ module Orchestration
12
21
  end
13
22
 
14
23
  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
24
+ self.class.database_adapter_name
21
25
  end
22
26
 
23
27
  def database_adapter
@@ -32,7 +36,7 @@ module Orchestration
32
36
  end
33
37
 
34
38
  def local_port(name, remote_port = nil)
35
- return nil if ports(name).empty?
39
+ return nil unless listener?(name)
36
40
  return ports(name).first[:local].to_i if remote_port.nil?
37
41
 
38
42
  ports(name).find { |mapping| mapping[:remote] == remote_port }
@@ -46,6 +50,10 @@ module Orchestration
46
50
  @config ||= @env.docker_compose_config
47
51
  end
48
52
 
53
+ def listener?(name)
54
+ services.key?(name.to_s) && !ports(name).empty?
55
+ end
56
+
49
57
  def ports(name)
50
58
  services
51
59
  .fetch(name.to_s)
@@ -92,6 +92,9 @@ module Orchestration
92
92
  def database_yml
93
93
  return unless defined?(ActiveRecord)
94
94
 
95
+ adapter = DockerCompose::ComposeConfiguration.database_adapter_name
96
+ return if adapter == 'sqlite3'
97
+
95
98
  service_config('database.yml', Services::Database::Configuration)
96
99
  end
97
100
 
@@ -3,7 +3,7 @@
3
3
  module Orchestration
4
4
  class ServiceCheck
5
5
  ATTEMPT_LIMIT = ENV.fetch('ORCHESTRATION_RETRY_LIMIT', '10').to_i
6
- RETRY_INTERVAL = ENV.fetch('ORCHESTRATION_RETRY_INTERVAL', '5').to_i
6
+ RETRY_INTERVAL = ENV.fetch('ORCHESTRATION_RETRY_INTERVAL', '6').to_i
7
7
 
8
8
  def initialize(service, terminal, options = {})
9
9
  @service = service
@@ -12,7 +12,7 @@ module Orchestration
12
12
  true
13
13
  end
14
14
 
15
- def initialize(env, service_name = nil)
15
+ def initialize(env, service_name = nil, options = {})
16
16
  super
17
17
  @settings = {}
18
18
  end
@@ -13,7 +13,7 @@ module Orchestration
13
13
  end
14
14
 
15
15
  def friendly_config
16
- return "[#{adapter.name}]" if adapter.name == 'sqlite3'
16
+ return "[#{adapter.name}]" if sqlite?
17
17
 
18
18
  "[#{adapter.name}] #{host}:#{port}"
19
19
  end
@@ -29,6 +29,10 @@ module Orchestration
29
29
  }.transform_keys(&:to_s)
30
30
  end
31
31
 
32
+ def configured?
33
+ sqlite? || super
34
+ end
35
+
32
36
  def adapter
33
37
  url_adapter = url_config['adapter']
34
38
  file_adapter = file_config['adapter']
@@ -42,10 +46,20 @@ module Orchestration
42
46
 
43
47
  private
44
48
 
49
+ def custom?
50
+ !@options[:config_path].nil?
51
+ end
52
+
53
+ def database_configuration_path
54
+ return @env.database_configuration_path unless custom?
55
+
56
+ @options[:config_path]
57
+ end
58
+
45
59
  def file_config
46
- return {} unless File.exist?(@env.database_configuration_path)
60
+ return {} unless File.exist?(database_configuration_path) || custom?
47
61
 
48
- yaml = ERB.new(File.read(env.database_configuration_path)).result
62
+ yaml = ERB.new(File.read(database_configuration_path)).result
49
63
  YAML.safe_load(yaml, [], [], true)[@env.environment] || {}
50
64
  end
51
65
 
@@ -67,6 +81,8 @@ module Orchestration
67
81
  end
68
82
 
69
83
  def port
84
+ return nil if sqlite?
85
+
70
86
  url_config['port'] || file_config['port'] || super
71
87
  end
72
88
 
@@ -109,6 +125,10 @@ module Orchestration
109
125
  def adapters
110
126
  Orchestration::Services::Database::Adapters
111
127
  end
128
+
129
+ def sqlite?
130
+ adapter.name == 'sqlite3'
131
+ end
112
132
  end
113
133
  end
114
134
  end
@@ -9,6 +9,8 @@ module Orchestration
9
9
  dependencies 'active_record'
10
10
 
11
11
  def connect
12
+ return if settings[:adapter] == 'sqlite3'
13
+
12
14
  ActiveRecord::Base.establish_connection(settings)
13
15
  ActiveRecord::Base.connection
14
16
  end
@@ -24,12 +26,7 @@ module Orchestration
24
26
  end
25
27
 
26
28
  def settings
27
- return @configuration.settings unless @options[:init]
28
-
29
- {
30
- adapter: @configuration.adapter.name,
31
- port: DockerCompose::DatabaseService::PORT
32
- }.merge(@configuration.adapter.credentials)
29
+ @configuration.settings
33
30
  end
34
31
  end
35
32
  end
@@ -22,8 +22,9 @@ module Orchestration
22
22
  end
23
23
  end
24
24
 
25
- def initialize(env, service_name = nil)
25
+ def initialize(env, service_name = nil, options = {})
26
26
  @env = env
27
+ @options = options
27
28
  @service_name = service_name || self.class.service_name
28
29
  end
29
30
 
@@ -37,7 +37,7 @@ module Orchestration
37
37
 
38
38
  def initialize(env, service_name = nil, options = {})
39
39
  @options = options
40
- @configuration = configuration_class.new(env, service_name)
40
+ @configuration = configuration_class.new(env, service_name, options)
41
41
  end
42
42
 
43
43
  def service_name
@@ -208,14 +208,14 @@ endif
208
208
  @bundle_path="${path}" ; tar -C '${orchestration_dir}/.deploy' -cf "$${bundle_path:-./bundle.tar}" ./${docker_repository}
209
209
 
210
210
  .PHONY: deploy
211
- ifndef manager
212
- @$(call println_error,'Missing `manager` parameter: `make deploy manager=swarm-manager.example.com`')
213
- endif
214
211
  deploy: path := $(shell mktemp -d)
215
212
  deploy: RAILS_ENV := ${env}
216
213
  deploy: RACK_ENV := ${env}
217
214
  deploy: DOCKER_TAG = ${git_version}
218
215
  deploy:
216
+ ifndef manager
217
+ @$(call println_error,'Missing `manager` parameter: `make deploy manager=swarm-manager.example.com`') ; exit 1
218
+ endif
219
219
  @$(call println,'${yellow}Deploying stack via${reset} ${green}${manager}${reset} ...') && \
220
220
  ( \
221
221
  $(call make,_verify_compose env_file=${env_file} env=${env}) && \
@@ -238,6 +238,18 @@ deploy:
238
238
 
239
239
  @$(call println,'${yellow}Deployment${reset} ${green}complete${reset}. ${tick}')
240
240
 
241
+ .PHONY: rollback
242
+ ifndef service
243
+ rollback: service = app
244
+ endif
245
+ rollback:
246
+ ifndef manager
247
+ @$(call println_error,'Missing `manager` parameter: `make deploy manager=swarm-manager.example.com`') ; exit 1
248
+ endif
249
+ @$(call println,'${yellow}Rolling back${reset} ${green}${project_name}_${service}${reset} ${yellow}via${reset} ${green}${manager}${reset} ...')
250
+ @ssh "${manager}" 'docker service rollback --detach "${project_name}_${service}"' ${log} || ${fail}
251
+ @$(call println,'${yellow}Rollback request${reset} ${green}complete${reset}. ${tick}')
252
+
241
253
  ### Service healthcheck commands ###
242
254
 
243
255
  .PHONY: wait
@@ -261,8 +273,14 @@ wait-listener:
261
273
  <% services.each do |service| %>
262
274
  <% next if service.to_sym == :app %>
263
275
  .PHONY: wait-<%= service %>
276
+ ifdef config
277
+ wait-<%= service %>: configvar := config=$(config)
278
+ endif
279
+ ifdef service
280
+ wait-<%= service %>: servicevar := service=$(service)
281
+ endif
264
282
  wait-<%= service %>:
265
- @${rake} orchestration:<%= service %>:wait
283
+ @${rake} orchestration:<%= service %>:wait $(configvar) $(servicevar)
266
284
 
267
285
  <% end %>
268
286
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Orchestration
4
- VERSION = '0.4.8'
4
+ VERSION = '0.4.9'
5
5
  end
@@ -8,10 +8,19 @@ namespace :orchestration do
8
8
  Orchestration::InstallGenerator.start
9
9
  end
10
10
 
11
+ namespace :install do
12
+ desc I18n.t('orchestration.rake.install_makefile')
13
+ task :makefile do
14
+ Orchestration::InstallGenerator.new.orchestration_makefile
15
+ end
16
+ end
17
+
11
18
  namespace :app do
12
19
  desc I18n.t('orchestration.rake.app.wait')
13
20
  task :wait do
14
- Orchestration::Services::App::Healthcheck.start
21
+ Orchestration::Services::App::Healthcheck.start(
22
+ nil, nil, config_path: ENV['config'], service_name: ENV['service']
23
+ )
15
24
  end
16
25
  end
17
26
 
@@ -19,7 +28,7 @@ namespace :orchestration do
19
28
  desc I18n.t('orchestration.rake.database.wait')
20
29
  task :wait do
21
30
  Orchestration::Services::Database::Healthcheck.start(
22
- nil, nil, init: ENV.key?('init')
31
+ nil, nil, config_path: ENV['config'], service_name: ENV['service']
23
32
  )
24
33
  end
25
34
  end
@@ -27,14 +36,18 @@ namespace :orchestration do
27
36
  namespace :mongo do
28
37
  desc I18n.t('orchestration.rake.mongo.wait')
29
38
  task :wait do
30
- Orchestration::Services::Mongo::Healthcheck.start
39
+ Orchestration::Services::Mongo::Healthcheck.start(
40
+ nil, nil, config_path: ENV['config'], service_name: ENV['service']
41
+ )
31
42
  end
32
43
  end
33
44
 
34
45
  namespace :rabbitmq do
35
46
  desc I18n.t('orchestration.rake.rabbitmq.wait')
36
47
  task :wait do
37
- Orchestration::Services::RabbitMQ::Healthcheck.start
48
+ Orchestration::Services::RabbitMQ::Healthcheck.start(
49
+ nil, nil, config_path: ENV['config'], service_name: ENV['service']
50
+ )
38
51
  end
39
52
  end
40
53
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: orchestration
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.8
4
+ version: 0.4.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bob Farrell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-09 00:00:00.000000000 Z
11
+ date: 2019-11-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: database_url