indocker 0.1.7 → 0.1.12

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