orchestration 0.4.10 → 0.4.12

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: 23e3a1c23b6511daf4d79650fb8cbae39b697f7f70ae9924ac69c69cc58f5f39
4
- data.tar.gz: b41de78b238b8663070651b20e36f40c8d430a89c5173ce28042c434ddcf6898
3
+ metadata.gz: 9f875ac821552fa3fb97823f27d3883b9d3ac93305a5adb42eedc10322930bf3
4
+ data.tar.gz: fbe1fd7262d71100122faa46f98ad27bcf94f3cb02b8894b9cf23af11bc0abae
5
5
  SHA512:
6
- metadata.gz: 5facd62ea505866177a36e837e93244e3314909b71091f6bca63aed73d37f8bb1b7f4837ee7824bad659da660cb5ec862750ff84550769025a868f35bf2fd338
7
- data.tar.gz: e8da0ea3bd75f817735e67604299ee93058bc7900f37bceb17b2f25b9228cd5e77c8a5503239ad6105bbf8dc097341ecef086448e16e5ba36975ea461116f875
6
+ metadata.gz: a7650ee86ba929d95a4cfdc1eb6324b053c36acdd9e3e9eab105a85dd763485643855eb3b4a458292cdb5b68f35a83447d4e057477f2f326c416e4044a06db17
7
+ data.tar.gz: 640be0c857fbcadeb6eac07852b7255b2c67a0591efb9195537f942ad9be80163b386dba5b2147fe65e46769a399149bbf2088cfcc34493dbcff0344ac946db5
data/.gitignore CHANGED
@@ -21,6 +21,7 @@ spec/dummy/Makefile
21
21
  spec/dummy/orchestration/*
22
22
  spec/dummy/config/unicorn.rb
23
23
  spec/dummy/config/*.bak
24
+ spec/dummy/tmp/*
24
25
 
25
26
  orchestration-*.gem
26
27
 
@@ -32,3 +33,5 @@ docker/.build/
32
33
  docker/.context.tar
33
34
 
34
35
  .DS_Store
36
+
37
+ .ruby-version
data/MANIFEST CHANGED
@@ -21,6 +21,7 @@ lib/orchestration.rb
21
21
  lib/orchestration/docker_compose.rb
22
22
  lib/orchestration/docker_compose/app_service.rb
23
23
  lib/orchestration/docker_compose/compose_configuration.rb
24
+ lib/orchestration/docker_compose/compose_helpers.rb
24
25
  lib/orchestration/docker_compose/configuration.rb
25
26
  lib/orchestration/docker_compose/database_service.rb
26
27
  lib/orchestration/docker_compose/install_generator.rb
data/Makefile CHANGED
@@ -1,8 +1,8 @@
1
1
  .PHONY: test
2
2
  test:
3
- ./bin/rspec
4
- ./bin/rubocop
5
- ./bin/strong_versions
3
+ bundle exec rspec
4
+ bundle exec rubocop
5
+ bundle exec strong_versions
6
6
 
7
7
  .PHONY: manifest
8
8
  manifest:
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.10'
38
+ gem 'orchestration', '~> 0.4.12'
39
39
  ```
40
40
 
41
41
  Install:
@@ -336,6 +336,20 @@ To do this automatically, pass the `sidecar` parameter to the `start` or `test`
336
336
  make test sidecar=1
337
337
  ```
338
338
 
339
+ When running in sidecar mode container-to-container networking is used so there is no benefit to binding dependency containers to a specific port on the host machine (only the target port will be used). For this reason a random, ephemeral port (chosen by _Docker_) will be used to allow multiple instances of each dependency to run alongside one another.
340
+
341
+ The _Docker Compose_ project name (and derived network name) is also suffixed with a random token to avoid container/network name conflicts.
342
+
343
+ Note that a temporary file `orchestration/.sidecar` containing the random project name suffix will be created when sidecar mode is used. If this file exists then sidecar mode is always assumed to be _on_. This is to allow (e.g.) stopping services that have been started separately with another command, for example:
344
+
345
+ ```bash
346
+ # Start dependencies and run tests in sidecar mode
347
+ make test sidecar=1
348
+
349
+ # Stop test dependencies in sidecar mode
350
+ make stop env=test
351
+ ```
352
+
339
353
  <a name="rabbitmq-configuration"></a>
340
354
  ## RabbitMQ Configuration
341
355
 
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Orchestration
4
+ module DockerCompose
5
+ module ComposeHelpers
6
+ def sidecar_port(environment)
7
+ port = Orchestration.random_local_port
8
+ return "#{port}:" unless environment == :test
9
+
10
+ # If env var `sidecar` is not set then ports will be configured as e.g.:
11
+ # "50123:3306"
12
+ # otherwise it will be:
13
+ # "3306" (docker will use an ephemeral host port which we will not use)
14
+ "${#{port}\:-sidecar}"
15
+ end
16
+ end
17
+ end
18
+ end
@@ -3,6 +3,8 @@
3
3
  module Orchestration
4
4
  module DockerCompose
5
5
  class DatabaseService
6
+ include ComposeHelpers
7
+
6
8
  def initialize(config, environment)
7
9
  @environment = environment
8
10
  @config = config
@@ -33,7 +35,7 @@ module Orchestration
33
35
  def ports
34
36
  return {} unless %i[development test].include?(@environment)
35
37
 
36
- { 'ports' => ["#{Orchestration.random_local_port}:#{remote_port}"] }
38
+ { 'ports' => ["#{sidecar_port(@environment)}#{remote_port}"] }
37
39
  end
38
40
 
39
41
  def volumes
@@ -3,6 +3,8 @@
3
3
  module Orchestration
4
4
  module DockerCompose
5
5
  class MongoService
6
+ include ComposeHelpers
7
+
6
8
  PORT = 27_020
7
9
 
8
10
  def initialize(config, environment)
@@ -21,7 +23,7 @@ module Orchestration
21
23
  def ports
22
24
  return {} unless %i[development test].include?(@environment)
23
25
 
24
- { 'ports' => ["#{local_port}:#{remote_port}"] }
26
+ { 'ports' => ["#{sidecar_port(@environment)}#{remote_port}"] }
25
27
  end
26
28
 
27
29
  def volumes
@@ -3,6 +3,8 @@
3
3
  module Orchestration
4
4
  module DockerCompose
5
5
  class RabbitMQService
6
+ include ComposeHelpers
7
+
6
8
  def initialize(config, environment)
7
9
  @config = config
8
10
  @environment = environment
@@ -19,7 +21,7 @@ module Orchestration
19
21
 
20
22
  container_port = Orchestration::Services::RabbitMQ::PORT
21
23
 
22
- { 'ports' => ["#{Orchestration.random_local_port}:#{container_port}"] }
24
+ { 'ports' => ["#{sidecar_port(@environment)}#{container_port}"] }
23
25
  end
24
26
  end
25
27
  end
@@ -5,6 +5,7 @@ module Orchestration
5
5
  end
6
6
  end
7
7
 
8
+ require 'orchestration/docker_compose/compose_helpers'
8
9
  require 'orchestration/docker_compose/install_generator'
9
10
  require 'orchestration/docker_compose/configuration'
10
11
  require 'orchestration/docker_compose/compose_configuration'
@@ -57,11 +57,11 @@ module Orchestration
57
57
  def gitignore
58
58
  path = @env.root.join('.gitignore')
59
59
  globs = %w[.build/ .deploy/ Gemfile Gemfile.lock docker-compose.local.yml]
60
- entries = %w[.env deploy.tar] + globs.map do |entry|
61
- "#{@env.orchestration_dir_name}/#{entry}"
60
+ lines = %w[orchestration/.sidecar .env deploy.tar] + globs.map do |line|
61
+ "#{@env.orchestration_dir_name}/#{line}"
62
62
  end
63
63
 
64
- ensure_lines_in_file(path, entries)
64
+ ensure_lines_in_file(path, lines)
65
65
  end
66
66
 
67
67
  def docker_compose
@@ -73,10 +73,14 @@ module Orchestration
73
73
  # A quirk of DatabaseUrl is that if no "/path" is present then the
74
74
  # `database` component is an empty string. In this unique case, we
75
75
  # want `nil` instead so that we can delegate to a default.
76
- config['database'] = nil if config['database']&.empty?
76
+ config['database'] = nil if database_missing?(config)
77
77
  config
78
78
  end
79
79
 
80
+ def database_missing?(config)
81
+ config.key?('database') && config['database'].empty?
82
+ end
83
+
80
84
  def host
81
85
  url_config['host'] || file_config['host'] || super
82
86
  end
@@ -37,8 +37,8 @@ module Orchestration
37
37
  def configured?
38
38
  port
39
39
  true
40
- rescue KeyError => error
41
- @error = error
40
+ rescue KeyError => e
41
+ @error = e
42
42
  false
43
43
  end
44
44
 
@@ -9,6 +9,9 @@ development:
9
9
  username: <%= compose.call(nil).database_adapter.credentials['username'] %>
10
10
  password: <%= compose.call(nil).database_adapter.credentials['password'] %>
11
11
  database: <%= compose.call(nil).database_adapter.credentials['database'] %>
12
+ <%% if ENV.key?('DEVELOPMENT_DATABASE_URL') %>
13
+ url: <%%= ENV['DEVELOPMENT_DATABASE_URL'] %>
14
+ <%% end %>
12
15
  <% end %>
13
16
 
14
17
  <% if compose.call('test').services.key?('database') %>
@@ -49,7 +49,7 @@ managed_env_tag:=\# -|- ORCHESTRATION
49
49
  standard_env_path:=${pwd}/.env
50
50
  backup_env_path:=${pwd}/.env.orchestration.backup
51
51
  is_managed_env:=$$(test -f '${standard_env_path}' && tail -n 1 '${standard_env_path}') == "${managed_env_tag}"*
52
-
52
+ token:=$(shell cat /dev/urandom | LC_CTYPE=C tr -dc 'a-z0-9' | fold -w8 | head -n1)
53
53
  back_up_env:=( \
54
54
  [ ! -f '${standard_env_path}' ] \
55
55
  || \
@@ -40,13 +40,36 @@ docker_organization=$(shell bash ${orchestration_dir}/yaml.bash docker_organizat
40
40
  docker_repository=$(shell bash ${orchestration_dir}/yaml.bash docker_repository)
41
41
 
42
42
  ifeq (,$(project_name))
43
- project_name = ${docker_repository}_${env}
43
+ project_base = ${docker_repository}_${env}
44
+ else
45
+ project_base := $(project_name)
46
+ endif
47
+
48
+ sidecar_suffix := $(shell test -f ${orchestration_dir}/.sidecar && cat ${orchestration_dir}/.sidecar)
49
+ ifneq (,${sidecar_suffix})
50
+ sidecar := 1
51
+ endif
52
+
53
+ ifdef sidecar
54
+ sidecar_compose = sidecar=1
55
+ ifeq (,${sidecar_suffix})
56
+ sidecar_suffix := $(call token)
57
+ _ignore := $(shell echo ${sidecar_suffix} > ${orchestration_dir}/.sidecar)
58
+ endif
59
+
60
+ ifeq (,${sidecar_suffix})
61
+ $(warning Unable to generate project suffix; project name collisions may occur.)
62
+ endif
63
+ compose_project_name = ${project_base}_${sidecar_suffix}
64
+ else
65
+ compose_project_name = ${project_base}
44
66
  endif
45
67
 
46
68
  compose_base=env HOST_UID=$(shell id -u) \
47
69
  DOCKER_ORGANIZATION="${docker_organization}" \
48
70
  DOCKER_REPOSITORY="${docker_repository}" \
49
- COMPOSE_PROJECT_NAME="${project_name}" \
71
+ COMPOSE_PROJECT_NAME="${compose_project_name}" \
72
+ ${sidecar_compose} \
50
73
  docker-compose \
51
74
  -f "${orchestration_dir}/docker-compose.yml"
52
75
 
@@ -67,7 +90,7 @@ all: build
67
90
 
68
91
  .PHONY: start
69
92
  ifndef network
70
- start: network := ${docker_repository}_${env}_default
93
+ start: network := ${compose_project_name}_default
71
94
  endif
72
95
  start: _clean-logs
73
96
  @$(call print,'${yellow}Starting containers${reset} ...')
@@ -75,9 +98,13 @@ ifeq (${env},$(filter ${env},test development))
75
98
  @${compose} up --detach --force-recreate --renew-anon-volumes ${services} ${log} || ${fail}
76
99
  @[ -n '${sidecar}' ] && \
77
100
  ( \
101
+ $(call printraw,' ${yellow}(joining dependency network ${green}${network}${yellow})${reset} ... ') ; \
78
102
  docker network connect '${network}' '$(shell hostname)' ${log} \
79
- || \
80
- $(call println,'${yellow}Warning${reset}: Unable to join network: "${yellow}${network}${reset}". Container will not be able to connect to dependency services.') \
103
+ || ( \
104
+ $(call println,'') ; \
105
+ $(call println,'${yellow}Warning${reset}: Unable to join network: "${yellow}${network}${reset}". Container will not be able to connect to dependency services.') ; \
106
+ $(call print,'You may need to delete "${yellow}orchestration/.sidecar${reset}" to disable sidecar mode if this file was added by mistake.\n...') ; \
107
+ ) \
81
108
  ) \
82
109
  || ( [ -z '${sidecar}' ] || ${fail} )
83
110
  else
@@ -99,13 +126,14 @@ start-<%= service %>:
99
126
  <% end %>
100
127
 
101
128
  .PHONY: stop
129
+ stop: network := ${compose_project_name}_default
102
130
  stop: _clean-logs
103
131
  @$(call print,'${yellow}Stopping containers${reset} ...')
104
132
  @if docker ps --format "{{.ID}}" | grep -q $(shell hostname) ; \
105
133
  then \
106
- ( ${compose} down ${log} || ${fail} ) \
134
+ ( docker network disconnect ${network} $(shell hostname) ${log} || : ) \
107
135
  && \
108
- ( docker network connect ${docker_repository}_${env}_default $(shell hostname) ${log} || : ) ; \
136
+ ( ${compose} down ${log} || ${fail} ) ; \
109
137
  else \
110
138
  ${compose} down ${log} || ${fail} ; \
111
139
  fi
@@ -231,7 +259,7 @@ endif
231
259
  echo 'DOCKER_TAG=${git_version}' >> ./.env && \
232
260
  $(call println,'') && \
233
261
  $(call println,'${yellow}Application image${reset}: ${cyan}${docker_image}${reset}') && \
234
- ${compose} config 2>${stderr} | ssh "${manager}" 'docker stack deploy --prune --with-registry-auth -c - "${project_name}"' ${log} && \
262
+ ${compose} config 2>${stderr} | ssh "${manager}" 'docker stack deploy --prune --with-registry-auth -c - "${project_base}"' ${log} && \
235
263
  ( [ -z "${path}" ] || rm -rf "${path}" ${log} ) \
236
264
  ) \
237
265
  || ${fail}
@@ -246,8 +274,8 @@ rollback:
246
274
  ifndef manager
247
275
  @$(call println_error,'Missing `manager` parameter: `make deploy manager=swarm-manager.example.com`') ; exit 1
248
276
  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}
277
+ @$(call println,'${yellow}Rolling back${reset} ${green}${compose_project_name}_${service}${reset} ${yellow}via${reset} ${green}${manager}${reset} ...')
278
+ @ssh "${manager}" 'docker service rollback --detach "${compose_project_name}_${service}"' ${log} || ${fail}
251
279
  @$(call println,'${yellow}Rollback request${reset} ${green}complete${reset}. ${tick}')
252
280
 
253
281
  ### Service healthcheck commands ###
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Orchestration
4
- VERSION = '0.4.10'
4
+ VERSION = '0.4.12'
5
5
  end
data/lib/orchestration.rb CHANGED
@@ -11,7 +11,7 @@ require 'paint'
11
11
  begin
12
12
  require 'rails'
13
13
  rescue LoadError
14
- STDERR.puts('[orchestration] Rails not detected; skipping.')
14
+ warn('[orchestration] Rails not detected; skipping.')
15
15
  end
16
16
 
17
17
  I18n.load_path += Dir[File.join(File.expand_path('..', __dir__),
@@ -40,8 +40,8 @@ module Orchestration
40
40
  end
41
41
 
42
42
  def self.error(key, options = {})
43
- STDERR.puts('# Orchestration Error')
44
- STDERR.puts('# ' + I18n.t("orchestration.#{key}", options))
43
+ warn('# Orchestration Error')
44
+ warn('# ' + I18n.t("orchestration.#{key}", options))
45
45
  end
46
46
 
47
47
  def self.random_local_port
@@ -40,7 +40,7 @@ Gem::Specification.new do |spec|
40
40
  spec.add_development_dependency 'rake', '~> 10.0'
41
41
  spec.add_development_dependency 'rspec', '~> 3.0'
42
42
  spec.add_development_dependency 'rspec-its', '~> 1.2'
43
- spec.add_development_dependency 'rubocop', '~> 0.59.2'
43
+ spec.add_development_dependency 'rubocop', '~> 0.77.0'
44
44
  spec.add_development_dependency 'sqlite3', '~> 1.3'
45
45
  spec.add_development_dependency 'strong_versions', '~> 0.3.1'
46
46
  spec.add_development_dependency 'webmock', '~> 3.4'
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.10
4
+ version: 0.4.12
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-11-08 00:00:00.000000000 Z
11
+ date: 2019-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: database_url
@@ -254,14 +254,14 @@ dependencies:
254
254
  requirements:
255
255
  - - "~>"
256
256
  - !ruby/object:Gem::Version
257
- version: 0.59.2
257
+ version: 0.77.0
258
258
  type: :development
259
259
  prerelease: false
260
260
  version_requirements: !ruby/object:Gem::Requirement
261
261
  requirements:
262
262
  - - "~>"
263
263
  - !ruby/object:Gem::Version
264
- version: 0.59.2
264
+ version: 0.77.0
265
265
  - !ruby/object:Gem::Dependency
266
266
  name: sqlite3
267
267
  requirement: !ruby/object:Gem::Requirement
@@ -339,6 +339,7 @@ files:
339
339
  - lib/orchestration/docker_compose.rb
340
340
  - lib/orchestration/docker_compose/app_service.rb
341
341
  - lib/orchestration/docker_compose/compose_configuration.rb
342
+ - lib/orchestration/docker_compose/compose_helpers.rb
342
343
  - lib/orchestration/docker_compose/configuration.rb
343
344
  - lib/orchestration/docker_compose/database_service.rb
344
345
  - lib/orchestration/docker_compose/install_generator.rb
@@ -411,8 +412,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
411
412
  - !ruby/object:Gem::Version
412
413
  version: '0'
413
414
  requirements: []
414
- rubyforge_project:
415
- rubygems_version: 2.7.6
415
+ rubygems_version: 3.0.3
416
416
  signing_key:
417
417
  specification_version: 4
418
418
  summary: Docker orchestration toolkit