orchestration 0.4.8 → 0.4.9

Sign up to get free protection for your applications and to get access to all the features.
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