indocker 0.1.7 → 0.1.12

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -0
  3. data/Gemfile.lock +10 -4
  4. data/README.md +13 -2
  5. data/example/indocker/bin/deploy +19 -13
  6. data/example/indocker/bounded_contexts/shared/bad_container_build/Dockerfile +3 -0
  7. data/example/indocker/bounded_contexts/shared/bad_container_build/container.rb +5 -0
  8. data/example/indocker/bounded_contexts/shared/bad_container_build/image.rb +3 -0
  9. data/example/indocker/bounded_contexts/shared/bad_container_start/Dockerfile +8 -0
  10. data/example/indocker/bounded_contexts/shared/bad_container_start/build_context/bin/run +3 -0
  11. data/example/indocker/bounded_contexts/shared/bad_container_start/container.rb +5 -0
  12. data/example/indocker/bounded_contexts/shared/bad_container_start/image.rb +3 -0
  13. data/example/indocker/bounded_contexts/shared/good_container/Dockerfile +4 -0
  14. data/example/indocker/bounded_contexts/shared/good_container/container.rb +5 -0
  15. data/example/indocker/bounded_contexts/shared/good_container/image.rb +3 -0
  16. data/example/indocker/configurations/external.rb +18 -0
  17. data/example/indocker/infrastructure/build_servers.rb +11 -0
  18. data/example/indocker/infrastructure/servers.rb +11 -0
  19. data/example/indocker/setup.rb +1 -1
  20. data/example/spec/indocker_spec.rb +39 -0
  21. data/example/spec/spec_helper.rb +39 -0
  22. data/indocker.gemspec +1 -1
  23. data/lib/indocker.rb +37 -56
  24. data/lib/indocker/build_context.rb +15 -13
  25. data/lib/indocker/build_context_pool.rb +7 -1
  26. data/lib/indocker/configuration_deployer.rb +113 -87
  27. data/lib/indocker/container_deployer.rb +4 -1
  28. data/lib/indocker/deploy_context.rb +10 -8
  29. data/lib/indocker/deployment_policy.rb +22 -0
  30. data/lib/indocker/deployment_progress.rb +7 -2
  31. data/lib/indocker/images_compiler.rb +2 -1
  32. data/lib/indocker/logger_factory.rb +37 -0
  33. data/lib/indocker/server_pool.rb +9 -1
  34. data/lib/indocker/ssh_session.rb +18 -9
  35. data/lib/indocker/version.rb +1 -1
  36. metadata +19 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 405310bd24a8adfa838f82a3cac79f2fa125083ebcb4cf788d27332875d52353
4
- data.tar.gz: 12103e2edb743e5024f50496962883f271c095bcd6264934c3295309fbf8e762
3
+ metadata.gz: 288383229ce87e66ab3869aa6fcd5180e0a54d09ca4046ed32a4ec34550a564f
4
+ data.tar.gz: 77eed21c9ad07145d0141c8450495fd74b6336cea91fc76a5dc37909f3983ee6
5
5
  SHA512:
6
- metadata.gz: fd602a0202c99b48303ee69a129b9f8cbfa9d621a7d2ea3f84b1446613ed8210b7ad103005967ce0459407a49482fcababf1b72f27254b1e6d5fcc29175c2ceb
7
- data.tar.gz: 67f12a6d6b2715bde6034dbbc1b6e0a2c42bcc7c27a5e66fe40bde489db8f50cd42fb1805e03e04e35a76dd9a1f82bb754e942beba68a9fba5a4751614644dbb
6
+ metadata.gz: 6e91c51c6898841882c3543a31710b84db43e2fc20498174119b269eaa47f9caf260a0720d99645a03dd292d470be4adadaaec6d4cadebce1290998782a3156a
7
+ data.tar.gz: cbf4395ff9f1f21c56785fa926dbaf3af80f33cad68041fa4ee9c2e8cee85faa353f0efe9c34aa23707b47764e5a0c6b4359dacf1a50b17f4e02db003455689d
data/Gemfile CHANGED
@@ -4,3 +4,8 @@ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in indocker.gemspec
6
6
  gemspec
7
+
8
+ group :test do
9
+ gem 'rspec'
10
+ gem 'pry'
11
+ end
@@ -1,15 +1,20 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- indocker (0.1.7)
4
+ indocker (0.1.12)
5
5
  net-ssh
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
+ coderay (1.1.3)
10
11
  diff-lcs (1.3)
12
+ method_source (1.0.0)
11
13
  net-ssh (6.1.0)
12
- rake (10.5.0)
14
+ pry (0.13.1)
15
+ coderay (~> 1.1)
16
+ method_source (~> 1.0)
17
+ rake (12.3.3)
13
18
  rspec (3.9.0)
14
19
  rspec-core (~> 3.9.0)
15
20
  rspec-expectations (~> 3.9.0)
@@ -30,8 +35,9 @@ PLATFORMS
30
35
  DEPENDENCIES
31
36
  bundler (~> 1.17)
32
37
  indocker!
33
- rake (~> 10.0)
34
- rspec (~> 3.0)
38
+ pry
39
+ rake (~> 12.3.3)
40
+ rspec
35
41
 
36
42
  BUNDLED WITH
37
43
  1.17.3
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # InDocker
2
2
 
3
+ [![Codeship Status for ArtStation/indocker](https://app.codeship.com/projects/bf8888c0-b7e4-0138-fc1f-7e2faa53772a/status?branch=master)](https://app.codeship.com/projects/404716)
4
+
3
5
  Docker Containers Deployment
4
6
 
5
7
  ## Installation
@@ -8,11 +10,20 @@ Docker Containers Deployment
8
10
  $ gem install indocker
9
11
  ```
10
12
 
11
- ## Development: Launch example app
13
+ ## Development: Launch example app locally
14
+
15
+ ```ruby
16
+ cd example
17
+ indocker/bin/deploy -C dev -c ruby -d
18
+ ```
19
+
20
+ ## Development: Launch example with external host
21
+
22
+ NOTE: Default external host requires extra permissions.
12
23
 
13
24
  ```ruby
14
25
  cd example
15
- bundle exec indocker/bin/deploy -C dev -c ruby -d
26
+ indocker/bin/deploy -C external -c ruby -d
16
27
  ```
17
28
 
18
29
  ## License
@@ -8,9 +8,10 @@ configurations = list_configurations(File.expand_path(File.join(__dir__, '../con
8
8
  ARGV << '-h' if ARGV.empty?
9
9
 
10
10
  options = {
11
- skip_build: false,
12
- force_restart: false,
13
- skip_tags: [],
11
+ skip_build: false,
12
+ skip_deploy: false,
13
+ force_restart: false,
14
+ skip_tags: [],
14
15
  skip_force_restart: [],
15
16
  }
16
17
 
@@ -61,6 +62,10 @@ OptionParser.new do |opts|
61
62
  options[:skip_build] = true
62
63
  end
63
64
 
65
+ opts.on("-b", "--skip-deploy", "Skip image deploy") do |val|
66
+ options[:skip_deploy] = true
67
+ end
68
+
64
69
  opts.on("-y", "--auto-confirm", "Automatically confirm deployment") do |val|
65
70
  options[:auto_confirm] = true
66
71
  end
@@ -106,15 +111,16 @@ Indocker.set_configuration_name(options[:configuration])
106
111
  require_relative '../setup'
107
112
 
108
113
  Indocker.deploy(
109
- containers: options[:containers] || [],
110
- tags: options[:tags] || [],
111
- skip_containers: options[:skip_containers] || [],
112
- skip_dependent: !!options[:skip_dependent],
113
- servers: options[:servers] || [],
114
- skip_build: options[:skip_build],
115
- force_restart: options[:force_restart],
116
- skip_tags: options[:skip_tags] || [],
117
- skip_force_restart: options[:skip_force_restart] || [],
118
- auto_confirm: !!options[:auto_confirm],
114
+ containers: options[:containers] || [],
115
+ tags: options[:tags] || [],
116
+ skip_containers: options[:skip_containers] || [],
117
+ skip_dependent: !!options[:skip_dependent],
118
+ servers: options[:servers] || [],
119
+ skip_build: options[:skip_build],
120
+ skip_deploy: options[:skip_deploy],
121
+ force_restart: options[:force_restart],
122
+ skip_tags: options[:skip_tags] || [],
123
+ skip_force_restart: options[:skip_force_restart] || [],
124
+ auto_confirm: !!options[:auto_confirm],
119
125
  require_confirmation: !!options[:require_confirmation],
120
126
  )
@@ -0,0 +1,3 @@
1
+ FROM ruby:2.5.0
2
+
3
+ RUN some-unexisting-command
@@ -0,0 +1,5 @@
1
+ Indocker
2
+ .define_container(:bad_container_build)
3
+ .tags('bad_container_build', 'console=true')
4
+ .image(:bad_container_build)
5
+ .networks(:app_net)
@@ -0,0 +1,3 @@
1
+ Indocker
2
+ .define_image(:bad_container_build)
3
+ .registry(:default)
@@ -0,0 +1,8 @@
1
+ FROM ruby:2.5.0
2
+
3
+ RUN mkdir /app
4
+ WORKDIR /app
5
+
6
+ COPY bin bin
7
+
8
+ CMD ["bin/run"]
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ raise "Some error"
@@ -0,0 +1,5 @@
1
+ Indocker
2
+ .define_container(:bad_container_start)
3
+ .tags('bad_container_start', 'console=true')
4
+ .image(:bad_container_start)
5
+ .networks(:app_net)
@@ -0,0 +1,3 @@
1
+ Indocker
2
+ .define_image(:bad_container_start)
3
+ .registry(:default)
@@ -0,0 +1,4 @@
1
+ FROM ruby:2.5.0
2
+
3
+ RUN mkdir /app
4
+ WORKDIR /app
@@ -0,0 +1,5 @@
1
+ Indocker
2
+ .define_container(:good_container)
3
+ .tags('good_container', 'console=true')
4
+ .image(:good_container)
5
+ .networks(:app_net)
@@ -0,0 +1,3 @@
1
+ Indocker
2
+ .define_image(:good_container)
3
+ .registry(:default)
@@ -0,0 +1,18 @@
1
+ Indocker
2
+ .build_configuration(:external)
3
+ .use_registry(:dev, as: :default)
4
+ .use_build_server(:external_bs)
5
+ .enabled_containers(
6
+ ruby: {
7
+ servers: [:external],
8
+ },
9
+ good_container: {
10
+ servers: [:external],
11
+ },
12
+ bad_container_build: {
13
+ servers: [:external],
14
+ },
15
+ bad_container_start: {
16
+ servers: [:external],
17
+ }
18
+ )
@@ -5,4 +5,15 @@ Indocker.add_build_server(
5
5
  user: `whoami`.strip,
6
6
  port: 22
7
7
  )
8
+ )
9
+
10
+ external_host = ENV['INDOCKER_EXTERNAL_HOST'] || 'indocker.artstn.ninja'
11
+ external_user = ENV['INDOCKER_EXTERNAL_USER'] || 'indocker'
12
+ Indocker.add_build_server(
13
+ Indocker::BuildServer.new(
14
+ name: :external_bs,
15
+ host: external_host,
16
+ user: external_user,
17
+ port: 22
18
+ )
8
19
  )
@@ -5,4 +5,15 @@ Indocker.add_server(
5
5
  user: `whoami`.strip,
6
6
  port: 22
7
7
  )
8
+ )
9
+
10
+ external_host = ENV['INDOCKER_EXTERNAL_HOST'] || 'indocker.artstn.ninja'
11
+ external_user = ENV['INDOCKER_EXTERNAL_USER'] || 'indocker'
12
+ Indocker.add_server(
13
+ Indocker::Server.new(
14
+ name: :external,
15
+ host: external_host,
16
+ user: external_user,
17
+ port: 22
18
+ )
8
19
  )
@@ -3,7 +3,7 @@ require 'indocker'
3
3
  root_dir = File.join(__dir__, '..', '..')
4
4
 
5
5
  Indocker.set_root_dir(__dir__)
6
- Indocker.set_deploy_dir(File.join(root_dir, 'tmp', 'deployment'))
6
+ Indocker.set_deploy_dir('~/deployment')
7
7
 
8
8
  Indocker.set_dockerignore [
9
9
  'Dockerfile',
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Indocker do
4
+ it "has a version number" do
5
+ expect(Indocker::VERSION).not_to be nil
6
+ end
7
+
8
+ describe "successful deployment" do
9
+ it "doesn't raise any error" do
10
+ expect{
11
+ launch_deployment(containers: [:good_container])
12
+ }.to_not raise_error
13
+ end
14
+
15
+ it "shows a message about successful deploy" do
16
+ allow(Indocker.global_logger).to receive(:info).at_least(:once)
17
+
18
+ launch_deployment(containers: [:good_container])
19
+
20
+ expect(Indocker.global_logger).to have_received(:info).at_least(:once).with(/Deployment finished/)
21
+ end
22
+ end
23
+
24
+ describe "failed build" do
25
+ it "exits with an error" do
26
+ expect{
27
+ launch_deployment(containers: [:bad_container_build])
28
+ }.to raise_error(SystemExit)
29
+ end
30
+ end
31
+
32
+ describe "failed start" do
33
+ it "exits without error" do
34
+ expect{
35
+ launch_deployment(containers: [:bad_container_start])
36
+ }.to_not raise_error(SystemExit)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,39 @@
1
+ require "bundler/setup"
2
+ require "indocker"
3
+ require "pry"
4
+
5
+ RSpec.configure do |config|
6
+ # Enable flags like --only-failures and --next-failure
7
+ config.example_status_persistence_file_path = ".rspec_status"
8
+
9
+ # Disable RSpec exposing methods globally on `Module` and `main`
10
+ config.disable_monkey_patching!
11
+
12
+ config.expect_with :rspec do |c|
13
+ c.syntax = :expect
14
+ end
15
+ end
16
+
17
+ def launch_deployment(options = {})
18
+ require_relative '../indocker/bin/utils/configurations'
19
+
20
+ Indocker.set_configuration_name(options[:configuration] || "external")
21
+ require_relative '../indocker/setup'
22
+
23
+ Indocker.set_log_level(options[:debug] ? Logger::DEBUG : Logger::INFO)
24
+
25
+ Indocker.deploy(
26
+ containers: options[:containers] || [],
27
+ tags: options[:tags] || [],
28
+ skip_containers: options[:skip_containers] || [],
29
+ skip_dependent: !!options[:skip_dependent],
30
+ servers: options[:servers] || [],
31
+ skip_build: options[:skip_build],
32
+ skip_deploy: options[:skip_deploy],
33
+ force_restart: options[:force_restart],
34
+ skip_tags: options[:skip_tags] || [],
35
+ skip_force_restart: options[:skip_force_restart] || [],
36
+ auto_confirm: !!options[:auto_confirm],
37
+ require_confirmation: !!options[:require_confirmation],
38
+ )
39
+ end
@@ -25,6 +25,6 @@ Gem::Specification.new do |spec|
25
25
 
26
26
  spec.add_dependency "net-ssh"
27
27
  spec.add_development_dependency "bundler", "~> 1.17"
28
- spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "rake", "~> 12.3.3"
29
29
  spec.add_development_dependency "rspec", "~> 3.0"
30
30
  end
@@ -88,7 +88,9 @@ module Indocker
88
88
  autoload :SshResultLogger, 'ssh_result_logger'
89
89
  autoload :DeploymentProgress, 'deployment_progress'
90
90
  autoload :DeploymentChecker, 'deployment_checker'
91
+ autoload :DeploymentPolicy, 'deployment_policy'
91
92
  autoload :CrontabRedeployRulesBuilder, 'crontab_redeploy_rules_builder'
93
+ autoload :LoggerFactory, 'logger_factory'
92
94
 
93
95
  class << self
94
96
  def set_export_command(command)
@@ -318,22 +320,31 @@ module Indocker
318
320
  builder
319
321
  end
320
322
 
321
- def deploy(containers: [], skip_tags: [], tags: [], skip_dependent: false, skip_containers: [], servers: [], skip_build: false, force_restart: false, skip_force_restart: [], auto_confirm: false, require_confirmation: false)
323
+ def deploy(containers: [], skip_tags: [], tags: [], skip_dependent: false,
324
+ skip_containers: [], servers: [], skip_build: false, skip_deploy: false,
325
+ force_restart: false, skip_force_restart: [], auto_confirm: false,
326
+ require_confirmation: false)
327
+
328
+ deployment_policy = Indocker::DeploymentPolicy.new(
329
+ deploy_containers: containers,
330
+ deploy_tags: tags,
331
+ servers: servers,
332
+ skip_dependent: skip_dependent,
333
+ skip_containers: skip_containers,
334
+ skip_build: skip_build,
335
+ skip_deploy: skip_deploy,
336
+ skip_tags: skip_tags,
337
+ force_restart: force_restart,
338
+ skip_force_restart: skip_force_restart,
339
+ auto_confirm: auto_confirm,
340
+ require_confirmation: require_confirmation,
341
+ )
342
+
322
343
  Indocker::ConfigurationDeployer
323
- .new(Indocker.logger)
344
+ .new(logger: Indocker.logger, global_logger: Indocker.global_logger)
324
345
  .run(
325
- configuration: configuration,
326
- deploy_containers: containers,
327
- deploy_tags: tags,
328
- skip_dependent: skip_dependent,
329
- skip_containers: skip_containers,
330
- servers: servers,
331
- skip_build: skip_build,
332
- force_restart: force_restart,
333
- skip_tags: skip_tags,
334
- skip_force_restart: skip_force_restart,
335
- auto_confirm: auto_confirm,
336
- require_confirmation: require_confirmation,
346
+ configuration: configuration,
347
+ deployment_policy: deployment_policy
337
348
  )
338
349
  end
339
350
 
@@ -385,56 +396,26 @@ module Indocker
385
396
  Indocker::BuildContextHelper.new(Indocker.configuration, nil)
386
397
  end
387
398
 
399
+ # This logger outputs progress of the deployment
400
+ # It will not output anything for deployment without debug option
388
401
  def logger
389
402
  @logger ||= begin
390
- logger = if @log_level == Logger::DEBUG
391
- Logger.new(STDOUT)
403
+ logger_stdout = if @log_level == Logger::DEBUG
404
+ STDOUT
392
405
  else
393
- Logger.new(File.open(File::NULL, "w"))
394
- end
395
-
396
- logger.level = @log_level || Logger::INFO
397
-
398
- logger.formatter = proc do |severity, datetime, progname, msg|
399
- level = Logger::SEV_LABEL.index(severity)
400
-
401
- severity = case level
402
- when Logger::INFO
403
- severity.green
404
- when Logger::WARN
405
- severity.purple
406
- when Logger::DEBUG
407
- severity.yellow
408
- when Logger::ERROR
409
- severity.red
410
- when Logger::FATAL
411
- severity.red
412
- else
413
- severity
414
- end
415
-
416
- severity = severity.downcase
417
-
418
- if logger.debug?
419
- if msg == "{timestamp}"
420
- ""
421
- else
422
- "#{datetime.strftime("%Y/%m/%d %H:%M:%S")} #{severity}: #{msg}\n"
423
- end
424
- else
425
- # Use a nicer logging for not debug
426
- if msg == "{timestamp}"
427
- datetime.strftime("%Y/%m/%d %H:%M:%S\n").grey
428
- else
429
- " #{severity}: #{msg}\n"
430
- end
431
- end
406
+ File.open(File::NULL, "w")
432
407
  end
433
408
 
434
- logger
409
+ Indocker::LoggerFactory.create(logger_stdout, @log_level)
435
410
  end
436
411
  end
437
412
 
413
+ # Global logger would output data without dependency on how we deploy the progress
414
+ # Currently it will always output data to stdout
415
+ def global_logger
416
+ @global_logger ||= Indocker::LoggerFactory.create(STDOUT, @log_level)
417
+ end
418
+
438
419
  def set_log_level(level)
439
420
  @log_level = level
440
421
  end
@@ -3,22 +3,24 @@ require 'fileutils'
3
3
  class Indocker::BuildContext
4
4
  attr_reader :session, :server, :configuration, :helper, :logger
5
5
 
6
- def initialize(configuration:, build_server:, logger:)
6
+ def initialize(configuration:, build_server:, logger:, global_logger:)
7
7
  @configuration = configuration
8
8
  @logger = logger
9
9
  @helper = Indocker::BuildContextHelper.new(@configuration, @build_server)
10
10
  @server = build_server
11
+ @global_logger = global_logger
12
+ @compiled_images = Hash.new(false)
13
+ end
11
14
 
12
- if build_server
13
- @session = Indocker::SshSession.new(
14
- host: build_server.host,
15
- user: build_server.user,
16
- port: build_server.port,
17
- logger: @logger
18
- )
19
- end
15
+ def create_session!
16
+ return unless @server
20
17
 
21
- @compiled_images = Hash.new(false)
18
+ @session = Indocker::SshSession.new(
19
+ host: @server.host,
20
+ user: @server.user,
21
+ port: @server.port,
22
+ logger: @logger
23
+ )
22
24
  end
23
25
 
24
26
  def exec!(command)
@@ -69,10 +71,10 @@ class Indocker::BuildContext
69
71
  build_args = args.join(' ')
70
72
 
71
73
  res = Indocker::Docker.build(image.local_registry_url, build_args)
72
-
74
+
73
75
  if res.exit_status != 0
74
- @logger.error("image compilation :#{image.name} failed")
75
- @logger.error(res.stdout)
76
+ @global_logger.error("image compilation :#{image.name} failed")
77
+ @global_logger.error(res.stdout)
76
78
  exit 1
77
79
  end
78
80
 
@@ -1,17 +1,23 @@
1
1
  class Indocker::BuildContextPool
2
- def initialize(configuration:, logger:)
2
+ def initialize(configuration:, logger:, global_logger:)
3
3
  @logger = logger
4
4
  @configuration = configuration
5
+ @global_logger = global_logger
5
6
 
6
7
  @contexts = configuration.build_servers.map do |build_server|
7
8
  Indocker::BuildContext.new(
8
9
  logger: @logger,
9
10
  configuration: configuration,
10
11
  build_server: build_server,
12
+ global_logger: @global_logger,
11
13
  )
12
14
  end
13
15
  end
14
16
 
17
+ def create_sessions!
18
+ @contexts.each(&:create_session!)
19
+ end
20
+
15
21
  def get
16
22
  context = nil
17
23
 
@@ -5,92 +5,109 @@ require 'tempfile'
5
5
  class Indocker::ConfigurationDeployer
6
6
  REMOTE_OPERATION_TIMEOUT = 60
7
7
 
8
- def initialize(logger)
8
+ def initialize(logger:, global_logger:)
9
9
  Thread.abort_on_exception = true # abort all threads if exception occurs
10
10
 
11
11
  @logger = logger
12
- @global_logger = Logger.new(STDOUT)
13
- @global_logger.formatter = logger.formatter
12
+ @global_logger = global_logger
14
13
 
15
14
  @progress = Indocker::DeploymentProgress.new(
16
15
  Indocker.logger.level == Logger::DEBUG ? nil : Logger.new(STDOUT)
17
16
  )
18
17
  end
19
18
 
20
- def run(configuration:, deploy_containers:, skip_tags:, deploy_tags:, skip_dependent:,
21
- skip_containers:, servers:, skip_build:, force_restart:, skip_force_restart:, auto_confirm:, require_confirmation:)
19
+ # Launch deployment & measure the benchmark
20
+ def run(configuration:, deployment_policy:)
22
21
  build_context_pool = nil
23
22
  deployer = nil
24
23
 
25
24
  time = Benchmark.realtime do
26
- if force_restart
25
+ if deployment_policy.force_restart
27
26
  @logger.warn("WARNING. All containers will be forced to restart.")
28
27
  end
29
28
 
30
- if skip_build
29
+ if deployment_policy.skip_build
31
30
  @logger.warn("WARNING. Images build step will be skipped")
32
31
  end
33
32
 
34
- preload_containers(configuration)
35
-
36
- containers = find_deploy_containers(configuration, deploy_containers, deploy_tags, skip_dependent, skip_containers, servers, skip_tags, auto_confirm, require_confirmation)
37
- containers = containers.uniq {|c| c.name}
38
-
39
- clonner = Indocker::Repositories::Clonner.new(configuration, @logger)
40
-
41
- @global_logger.info("Establishing ssh sessions to all servers...")
42
-
43
- build_context_pool = Indocker::BuildContextPool.new(configuration: configuration, logger: @logger)
44
- deployer = Indocker::ContainerDeployer.new(configuration: configuration, logger: @logger)
45
-
46
- build_servers = configuration
47
- .build_servers
48
- .uniq { |s| s.host }
49
-
50
- deploy_servers = containers
51
- .map(&:servers)
52
- .flatten
53
- .uniq { |s| s.host }
33
+ if deployment_policy.skip_deploy
34
+ @logger.warn("WARNING. Images deploy step will be skipped")
35
+ end
54
36
 
55
- servers = (deploy_servers + build_servers).uniq { |s| s.host }
37
+ run!(configuration: configuration, deployment_policy: deployment_policy)
38
+ end
56
39
 
57
- @progress.setup(
58
- binaries_servers: servers,
59
- build_servers: build_servers,
60
- deploy_servers: deploy_servers,
61
- env_files: configuration.env_files.keys,
62
- repositories: configuration.repositories.keys,
63
- force_restart: force_restart,
64
- skip_build: skip_build,
65
- containers: containers,
66
- artifact_servers: configuration.artifact_servers,
67
- )
40
+ @global_logger.info("Deployment finished".green)
41
+ @global_logger.info("Total time taken: #{time.round}s".green)
42
+ end
68
43
 
69
- remote_operations = sync_indocker(servers)
70
- wait_remote_operations(remote_operations)
44
+ # The main flow of the deployment would happen in this method.
45
+ def run!(configuration:, deployment_policy:)
46
+ containers = find_containers_to_deploy(configuration, deployment_policy)
47
+
48
+ clonner = Indocker::Repositories::Clonner.new(configuration, @logger)
49
+ build_context_pool = Indocker::BuildContextPool.new(configuration: configuration, logger: @logger, global_logger: @global_logger)
50
+ deployer = Indocker::ContainerDeployer.new(configuration: configuration, logger: @logger)
51
+
52
+ @global_logger.info("Establishing ssh sessions to all servers...")
53
+ build_context_pool.create_sessions!
54
+ deployer.create_sessions!
55
+
56
+ build_servers = configuration
57
+ .build_servers
58
+ .uniq { |s| s.host }
59
+
60
+ deploy_servers = containers
61
+ .map(&:servers)
62
+ .flatten
63
+ .uniq { |s| s.host }
64
+
65
+ servers = (deploy_servers + build_servers).uniq { |s| s.host }
66
+
67
+ @progress.setup(
68
+ binaries_servers: servers,
69
+ build_servers: build_servers,
70
+ deploy_servers: deploy_servers,
71
+ env_files: configuration.env_files.keys,
72
+ repositories: configuration.repositories.keys,
73
+ force_restart: deployment_policy.force_restart,
74
+ skip_build: deployment_policy.skip_build,
75
+ skip_deploy: deployment_policy.skip_deploy,
76
+ containers: containers,
77
+ artifact_servers: configuration.artifact_servers,
78
+ )
71
79
 
72
- remote_operations = sync_env_files(deploy_servers, configuration.env_files)
73
- wait_remote_operations(remote_operations)
80
+ remote_operations = sync_indocker(servers)
81
+ wait_remote_operations(remote_operations)
74
82
 
75
- remote_operations = pull_repositories(clonner, build_servers, configuration.repositories)
76
- wait_remote_operations(remote_operations)
83
+ remote_operations = sync_env_files(deploy_servers, configuration.env_files)
84
+ wait_remote_operations(remote_operations)
77
85
 
78
- remote_operations = sync_artifacts(clonner, configuration.artifact_servers)
79
- wait_remote_operations(remote_operations)
86
+ remote_operations = pull_repositories(clonner, build_servers, configuration.repositories)
87
+ wait_remote_operations(remote_operations)
80
88
 
81
- update_crontab_redeploy_rules(configuration, build_servers.first)
89
+ remote_operations = sync_artifacts(clonner, configuration.artifact_servers)
90
+ wait_remote_operations(remote_operations)
82
91
 
83
- containers.uniq.each do |container|
84
- recursively_deploy_container(configuration, deployer, build_context_pool, container, containers, skip_build, force_restart, skip_force_restart)
85
- end
92
+ update_crontab_redeploy_rules(configuration, build_servers.first)
86
93
 
87
- Thread
88
- .list
89
- .each { |t| t.join if t != Thread.current }
94
+ containers.uniq.each do |container|
95
+ recursively_deploy_container(
96
+ configuration,
97
+ deployer,
98
+ build_context_pool,
99
+ container,
100
+ containers,
101
+ deployment_policy.skip_build,
102
+ deployment_policy.skip_deploy,
103
+ deployment_policy.force_restart,
104
+ deployment_policy.skip_force_restart
105
+ )
90
106
  end
91
107
 
92
- @global_logger.info("Deployment finished".green)
93
- @global_logger.info("Total time taken: #{time.round}s".green)
108
+ Thread
109
+ .list
110
+ .each { |t| t.join if t != Thread.current }
94
111
  ensure
95
112
  build_context_pool.close_sessions if build_context_pool
96
113
  deployer.close_sessions if deployer
@@ -111,23 +128,18 @@ class Indocker::ConfigurationDeployer
111
128
  end
112
129
  end
113
130
 
114
- def preload_containers(configuration)
115
- configuration.enabled_containers.each do |container_name|
116
- path = Indocker.container_files[container_name]
117
- require path
118
- end
119
- end
120
-
121
- def find_deploy_containers(configuration, deploy_containers, deploy_tags, skip_dependent, skip_containers, servers, skip_tags, auto_confirm, require_confirmation)
131
+ def find_containers_to_deploy(configuration, deployment_policy)
132
+ load_enabled_containers(configuration)
133
+
122
134
  containers = []
123
135
 
124
- deploy_tags.each do |tag|
136
+ deployment_policy.deploy_tags.each do |tag|
125
137
  containers += configuration.containers.select do |container|
126
138
  container.tags.include?(tag)
127
139
  end
128
140
  end
129
141
 
130
- skip_containers.each do |name|
142
+ deployment_policy.skip_containers.each do |name|
131
143
  container = configuration.containers.detect do |container|
132
144
  container.name == name
133
145
  end
@@ -144,7 +156,7 @@ class Indocker::ConfigurationDeployer
144
156
  end
145
157
  end
146
158
 
147
- deploy_containers.each do |name|
159
+ deployment_policy.deploy_containers.each do |name|
148
160
  container = configuration.containers.detect do |container|
149
161
  container.name == name
150
162
  end
@@ -158,17 +170,17 @@ class Indocker::ConfigurationDeployer
158
170
  end
159
171
  end
160
172
 
161
- if deploy_tags.empty? && deploy_containers.empty?
173
+ if deployment_policy.deploy_tags.empty? && deployment_policy.deploy_containers.empty?
162
174
  containers = configuration.containers.select do |container|
163
175
  configuration.enabled_containers.include?(container.name)
164
176
  end
165
177
  end
166
178
 
167
- if !skip_dependent
179
+ if !deployment_policy.skip_dependent
168
180
  containers = collect_dependent_containers(containers)
169
181
  end
170
182
 
171
- if !skip_dependent
183
+ if !deployment_policy.skip_dependent
172
184
  containers = collect_soft_dependent_containers(containers, configuration)
173
185
  end
174
186
 
@@ -181,13 +193,13 @@ class Indocker::ConfigurationDeployer
181
193
 
182
194
  containers = containers
183
195
  .select { |container| configuration.container_enabled?(container) }
184
- .select { |container| !skip_containers.include?(container.name) }
196
+ .select { |container| !deployment_policy.skip_containers.include?(container.name) }
185
197
  .select { |container|
186
- (skip_tags & container.tags).empty?
198
+ (deployment_policy.skip_tags & container.tags).empty?
187
199
  }
188
200
 
189
- if !servers.empty?
190
- containers = containers.select {|c| !(c.servers.map(&:name) & servers).empty? }
201
+ if !deployment_policy.servers.empty?
202
+ containers = containers.select {|c| !(c.servers.map(&:name) & deployment_policy.servers).empty? }
191
203
  end
192
204
 
193
205
  if containers.empty?
@@ -196,6 +208,7 @@ class Indocker::ConfigurationDeployer
196
208
  else
197
209
  @global_logger.info("Following containers will be deployed:")
198
210
 
211
+ servers = deployment_policy.servers
199
212
  if servers.empty?
200
213
  servers = containers.map(&:servers).flatten.uniq.map(&:name)
201
214
  end
@@ -213,7 +226,7 @@ class Indocker::ConfigurationDeployer
213
226
  end
214
227
  end
215
228
 
216
- if (require_confirmation || configuration.confirm_deployment) && !auto_confirm
229
+ if (deployment_policy.require_confirmation || configuration.confirm_deployment) && !deployment_policy.auto_confirm
217
230
  @global_logger.info("\n")
218
231
  @global_logger.info("Do you want to continue deployment? (y or n)")
219
232
  result = gets.chomp
@@ -224,7 +237,14 @@ class Indocker::ConfigurationDeployer
224
237
  end
225
238
  end
226
239
 
227
- containers
240
+ containers.uniq {|c| c.name}
241
+ end
242
+ end
243
+
244
+ def load_enabled_containers(configuration)
245
+ configuration.enabled_containers.each do |container_name|
246
+ path = Indocker.container_files[container_name]
247
+ require path
228
248
  end
229
249
  end
230
250
 
@@ -285,9 +305,21 @@ class Indocker::ConfigurationDeployer
285
305
  build_context.set_compiled(image)
286
306
  end
287
307
 
288
- def recursively_deploy_container(configuration, deployer, build_context_pool, container, containers, skip_build, force_restart, skip_force_restart)
308
+ def recursively_deploy_container(configuration, deployer, build_context_pool, container,
309
+ containers, skip_build, skip_deploy, force_restart, skip_force_restart)
310
+
289
311
  container.dependent_containers.each do |container|
290
- recursively_deploy_container(configuration, deployer, build_context_pool, container, containers, skip_build, force_restart, skip_force_restart)
312
+ recursively_deploy_container(
313
+ configuration,
314
+ deployer,
315
+ build_context_pool,
316
+ container,
317
+ containers,
318
+ skip_build,
319
+ skip_deploy,
320
+ force_restart,
321
+ skip_force_restart
322
+ )
291
323
  end
292
324
 
293
325
  return if !containers.include?(container)
@@ -304,7 +336,9 @@ class Indocker::ConfigurationDeployer
304
336
 
305
337
  @progress.finish_building_container(container)
306
338
 
307
- deployer.deploy(container, force_restart, skip_force_restart, @progress)
339
+ if !skip_deploy
340
+ deployer.deploy(container, force_restart, skip_force_restart, @progress)
341
+ end
308
342
  end
309
343
 
310
344
  class RemoteOperation
@@ -319,7 +353,6 @@ class Indocker::ConfigurationDeployer
319
353
  end
320
354
 
321
355
  def pull_repositories(clonner, servers, repositories)
322
- @logger.info("{timestamp}")
323
356
  @logger.info("Clonning/pulling repositories")
324
357
 
325
358
  remote_operations = []
@@ -372,7 +405,6 @@ class Indocker::ConfigurationDeployer
372
405
  end
373
406
 
374
407
  def sync_artifacts(clonner, artifact_servers)
375
- @logger.info("{timestamp}")
376
408
  @logger.info("Syncing git artifacts")
377
409
 
378
410
  remote_operations = []
@@ -424,8 +456,6 @@ class Indocker::ConfigurationDeployer
424
456
  redeploy_containers = configuration.containers.select {|c| c.redeploy_schedule}.uniq
425
457
  return if redeploy_containers.empty?
426
458
 
427
- @logger.info("{timestamp}")
428
-
429
459
  deploy_user = "#{server.user}@#{server.host}"
430
460
  crontab_filepath = Indocker.redeploy_crontab_path
431
461
 
@@ -450,8 +480,6 @@ class Indocker::ConfigurationDeployer
450
480
  end
451
481
 
452
482
  def sync_indocker(servers)
453
- @logger.info("{timestamp}")
454
-
455
483
  servers.map do |server|
456
484
  @progress.start_syncing_binaries(server)
457
485
 
@@ -482,8 +510,6 @@ class Indocker::ConfigurationDeployer
482
510
  end
483
511
 
484
512
  def sync_env_files(servers, env_files)
485
- @logger.info("{timestamp}")
486
-
487
513
  remote_operations = []
488
514
 
489
515
  servers.map do |server|
@@ -14,6 +14,10 @@ class Indocker::ContainerDeployer
14
14
  @deployed_servers = {}
15
15
  end
16
16
 
17
+ def create_sessions!
18
+ @server_pool.create_sessions!
19
+ end
20
+
17
21
  def deploy(container, force_restart, skip_force_restart, progress)
18
22
  return if @deployed_containers[container]
19
23
 
@@ -34,7 +38,6 @@ class Indocker::ContainerDeployer
34
38
 
35
39
  exec_proc.call do
36
40
  deploy_context = @server_pool.get(server)
37
- @logger.info("{timestamp}")
38
41
  @logger.info("Deploying container: #{container.name.to_s.green} to #{server.user}@#{server.host}")
39
42
 
40
43
  command_output = @logger.debug? ? "" : " > /dev/null"
@@ -9,15 +9,17 @@ class Indocker::DeployContext
9
9
  @configuration = configuration
10
10
  @server = server
11
11
  @restart_policy = Indocker::Containers::RestartPolicy.new(configuration, logger)
12
+ end
12
13
 
13
- if server
14
- @session = Indocker::SshSession.new(
15
- host: server.host,
16
- user: server.user,
17
- port: server.port,
18
- logger: @logger
19
- )
20
- end
14
+ def create_session!
15
+ return unless @server
16
+
17
+ @session = Indocker::SshSession.new(
18
+ host: @server.host,
19
+ user: @server.user,
20
+ port: @server.port,
21
+ logger: @logger
22
+ )
21
23
  end
22
24
 
23
25
  def exec!(command)
@@ -0,0 +1,22 @@
1
+ class Indocker::DeploymentPolicy
2
+ attr_reader :deploy_containers, :deploy_tags, :servers,
3
+ :skip_dependent, :skip_tags, :skip_containers, :skip_build, :skip_deploy,
4
+ :force_restart, :skip_force_restart, :auto_confirm, :require_confirmation
5
+
6
+ def initialize(deploy_containers:, deploy_tags:, servers:,
7
+ skip_dependent:, skip_tags:, skip_containers:, skip_build:, skip_deploy:,
8
+ force_restart:, skip_force_restart:, auto_confirm:, require_confirmation:)
9
+ @deploy_containers = deploy_containers
10
+ @deploy_tags = deploy_tags
11
+ @servers = servers
12
+ @skip_dependent = skip_dependent
13
+ @skip_tags = skip_tags
14
+ @skip_containers = skip_containers
15
+ @skip_build = skip_build
16
+ @skip_deploy = skip_deploy
17
+ @force_restart = force_restart
18
+ @skip_force_restart = skip_force_restart
19
+ @auto_confirm = auto_confirm
20
+ @require_confirmation = require_confirmation
21
+ end
22
+ end
@@ -70,9 +70,10 @@ class Indocker::DeploymentProgress
70
70
  end
71
71
 
72
72
  def setup(binaries_servers:, build_servers:, deploy_servers:, env_files:, artifact_servers:,
73
- repositories:, force_restart:, skip_build:, containers:)
73
+ repositories:, force_restart:, skip_build:, skip_deploy:, containers:)
74
74
  @force_restart = force_restart
75
- @skip_build = skip_build
75
+ @skip_build = skip_build
76
+ @skip_deploy = skip_deploy
76
77
 
77
78
  binaries_servers.each do |server|
78
79
  @synced_binaries[server] = {
@@ -250,6 +251,10 @@ class Indocker::DeploymentProgress
250
251
  @logger.info("Warning: Image build is skipped for all containers".purple)
251
252
  end
252
253
 
254
+ if @skip_deploy
255
+ @logger.info("Warning: All container deployment is skipped".purple)
256
+ end
257
+
253
258
  if @force_restart
254
259
  @logger.info("Warning: All containers will be force restarted".purple)
255
260
  end
@@ -9,7 +9,8 @@ class Indocker::ImagesCompiler
9
9
  build_context = Indocker::BuildContext.new(
10
10
  configuration: configuration,
11
11
  build_server: nil,
12
- logger: Indocker.logger
12
+ logger: @logger,
13
+ global_logger: Indocker.global_logger
13
14
  )
14
15
 
15
16
  image_compiler = Indocker::Images::ImageCompiler.new
@@ -0,0 +1,37 @@
1
+ class Indocker::LoggerFactory
2
+ class << self
3
+ def create(stdout, level = nil)
4
+ logger = Logger.new(stdout)
5
+
6
+ logger.level = level || Logger::INFO
7
+
8
+ logger.formatter = proc do |severity, datetime, progname, msg|
9
+ level = Logger::SEV_LABEL.index(severity)
10
+
11
+ severity = case level
12
+ when Logger::INFO
13
+ severity.green
14
+ when Logger::WARN
15
+ severity.purple
16
+ when Logger::DEBUG
17
+ severity.yellow
18
+ when Logger::ERROR
19
+ severity.red
20
+ when Logger::FATAL
21
+ severity.red
22
+ else
23
+ severity
24
+ end
25
+
26
+ severity = severity.downcase
27
+ if logger.debug?
28
+ "#{datetime.strftime("%Y/%m/%d %H:%M:%S")} #{severity}: #{msg}\n"
29
+ else
30
+ " #{severity}: #{msg}\n"
31
+ end
32
+ end
33
+
34
+ logger
35
+ end
36
+ end
37
+ end
@@ -12,12 +12,20 @@ class Indocker::ServerPool
12
12
  end
13
13
  end
14
14
 
15
+ def create_sessions!
16
+ @contexts.each(&:create_session!)
17
+ end
18
+
19
+ # NOTE: get is a bad name here, because we create a new connection.
20
+ # TODO: why we create a new connection here?
15
21
  def get(server)
16
- Indocker::DeployContext.new(
22
+ context = Indocker::DeployContext.new(
17
23
  logger: @logger,
18
24
  configuration: @configuration,
19
25
  server: server,
20
26
  )
27
+ context.create_session!
28
+ context
21
29
  end
22
30
 
23
31
  def each(&proc)
@@ -38,10 +38,26 @@ class Indocker::SshSession
38
38
  end
39
39
 
40
40
  def exec!(command)
41
- if !@ssh
41
+ if local?
42
+ exec_locally!(command)
43
+ else
44
+ exec_remotely!(command)
45
+ end
46
+ end
47
+
48
+ def close
49
+ if @ssh
50
+ @ssh.close
51
+ end
52
+ end
53
+
54
+ private
55
+ def exec_locally!(command)
42
56
  res = Indocker::Shell.command_with_result(command, @logger, skip_logging: false)
43
57
  ExecResult.new(res.stdout, '', res.exit_status, nil)
44
- else
58
+ end
59
+
60
+ def exec_remotely!(command)
45
61
  if Indocker.export_command
46
62
  command = "#{Indocker.export_command} && #{command}"
47
63
  end
@@ -82,11 +98,4 @@ class Indocker::SshSession
82
98
 
83
99
  ExecResult.new(stdout_data, stderr_data, exit_code, exit_signal)
84
100
  end
85
- end
86
-
87
- def close
88
- if @ssh
89
- @ssh.close
90
- end
91
- end
92
101
  end
@@ -1,3 +1,3 @@
1
1
  module Indocker
2
- VERSION = "0.1.7"
2
+ VERSION = "0.1.12"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: indocker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ruslan Gatiyatov
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-07-02 00:00:00.000000000 Z
12
+ date: 2020-08-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: net-ssh
@@ -45,14 +45,14 @@ dependencies:
45
45
  requirements:
46
46
  - - "~>"
47
47
  - !ruby/object:Gem::Version
48
- version: '10.0'
48
+ version: 12.3.3
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
53
  - - "~>"
54
54
  - !ruby/object:Gem::Version
55
- version: '10.0'
55
+ version: 12.3.3
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: rspec
58
58
  requirement: !ruby/object:Gem::Requirement
@@ -88,15 +88,28 @@ files:
88
88
  - example/indocker/bin/remote/compile
89
89
  - example/indocker/bin/remote/run
90
90
  - example/indocker/bin/utils/configurations.rb
91
+ - example/indocker/bounded_contexts/shared/bad_container_build/Dockerfile
92
+ - example/indocker/bounded_contexts/shared/bad_container_build/container.rb
93
+ - example/indocker/bounded_contexts/shared/bad_container_build/image.rb
94
+ - example/indocker/bounded_contexts/shared/bad_container_start/Dockerfile
95
+ - example/indocker/bounded_contexts/shared/bad_container_start/build_context/bin/run
96
+ - example/indocker/bounded_contexts/shared/bad_container_start/container.rb
97
+ - example/indocker/bounded_contexts/shared/bad_container_start/image.rb
98
+ - example/indocker/bounded_contexts/shared/good_container/Dockerfile
99
+ - example/indocker/bounded_contexts/shared/good_container/container.rb
100
+ - example/indocker/bounded_contexts/shared/good_container/image.rb
91
101
  - example/indocker/bounded_contexts/shared/ruby/Dockerfile
92
102
  - example/indocker/bounded_contexts/shared/ruby/container.rb
93
103
  - example/indocker/bounded_contexts/shared/ruby/image.rb
94
104
  - example/indocker/configurations/dev.rb
105
+ - example/indocker/configurations/external.rb
95
106
  - example/indocker/infrastructure/build_servers.rb
96
107
  - example/indocker/infrastructure/networks.rb
97
108
  - example/indocker/infrastructure/registries.rb
98
109
  - example/indocker/infrastructure/servers.rb
99
110
  - example/indocker/setup.rb
111
+ - example/spec/indocker_spec.rb
112
+ - example/spec/spec_helper.rb
100
113
  - indocker.gemspec
101
114
  - lib/indocker.rb
102
115
  - lib/indocker/artifacts/git.rb
@@ -120,6 +133,7 @@ files:
120
133
  - lib/indocker/crontab_redeploy_rules_builder.rb
121
134
  - lib/indocker/deploy_context.rb
122
135
  - lib/indocker/deployment_checker.rb
136
+ - lib/indocker/deployment_policy.rb
123
137
  - lib/indocker/deployment_progress.rb
124
138
  - lib/indocker/docker.rb
125
139
  - lib/indocker/docker_run_args.rb
@@ -134,6 +148,7 @@ files:
134
148
  - lib/indocker/images/templates_compiler.rb
135
149
  - lib/indocker/images_compiler.rb
136
150
  - lib/indocker/indocker_helper.rb
151
+ - lib/indocker/logger_factory.rb
137
152
  - lib/indocker/network.rb
138
153
  - lib/indocker/network_helper.rb
139
154
  - lib/indocker/registries/abstract.rb