indocker 0.0.6 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (183) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +10 -2
  3. data/.rspec +2 -0
  4. data/.travis.yml +7 -0
  5. data/Gemfile +5 -2
  6. data/Gemfile.lock +19 -49
  7. data/LICENSE.txt +17 -18
  8. data/README.md +20 -1
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/example/indocker/bin/deploy +120 -0
  13. data/example/indocker/bin/remote/compile +72 -0
  14. data/example/indocker/bin/remote/run +66 -0
  15. data/example/indocker/bin/utils/configurations.rb +3 -0
  16. data/example/indocker/bounded_contexts/shared/ruby/Dockerfile +10 -0
  17. data/example/indocker/bounded_contexts/shared/ruby/container.rb +5 -0
  18. data/example/indocker/bounded_contexts/shared/ruby/image.rb +3 -0
  19. data/example/indocker/configurations/dev.rb +9 -0
  20. data/example/indocker/infrastructure/build_servers.rb +8 -0
  21. data/example/indocker/infrastructure/networks.rb +1 -0
  22. data/example/indocker/infrastructure/registries.rb +3 -0
  23. data/example/indocker/infrastructure/servers.rb +8 -0
  24. data/example/indocker/setup.rb +24 -0
  25. data/indocker.gemspec +27 -25
  26. data/lib/indocker.rb +437 -130
  27. data/lib/indocker/artifacts/git.rb +25 -0
  28. data/lib/indocker/build_context.rb +87 -0
  29. data/lib/indocker/build_context_helper.rb +109 -0
  30. data/lib/indocker/build_context_pool.rb +36 -0
  31. data/lib/indocker/build_server.rb +2 -0
  32. data/lib/indocker/colored_string.rb +33 -0
  33. data/lib/indocker/concerns/inspectable.rb +12 -0
  34. data/lib/indocker/configuration_deployer.rb +525 -0
  35. data/lib/indocker/configurations/configuration.rb +122 -0
  36. data/lib/indocker/configurations/configuration_builder.rb +250 -0
  37. data/lib/indocker/configurations/formatters/stdout.rb +36 -0
  38. data/lib/indocker/container_deployer.rb +73 -0
  39. data/lib/indocker/container_helper.rb +13 -0
  40. data/lib/indocker/container_runner.rb +23 -0
  41. data/lib/indocker/containers/container.rb +118 -0
  42. data/lib/indocker/containers/container_builder.rb +186 -0
  43. data/lib/indocker/containers/restart_policy.rb +36 -0
  44. data/lib/indocker/context_args.rb +43 -0
  45. data/lib/indocker/crontab_redeploy_rules_builder.rb +54 -0
  46. data/lib/indocker/deploy_context.rb +126 -0
  47. data/lib/indocker/deployment_checker.rb +121 -0
  48. data/lib/indocker/deployment_progress.rb +495 -0
  49. data/lib/indocker/docker.rb +87 -0
  50. data/lib/indocker/docker_run_args.rb +183 -0
  51. data/lib/indocker/env_file_helper.rb +13 -0
  52. data/lib/indocker/env_files/local.rb +8 -0
  53. data/lib/indocker/env_files/remote.rb +8 -0
  54. data/lib/indocker/hash_merger.rb +9 -0
  55. data/lib/indocker/images/image.rb +86 -0
  56. data/lib/indocker/images/image_builder.rb +98 -0
  57. data/lib/indocker/images/image_compiler.rb +68 -0
  58. data/lib/indocker/images/template_compiler.rb +15 -0
  59. data/lib/indocker/images/templates_compiler.rb +28 -0
  60. data/lib/indocker/images_compiler.rb +38 -0
  61. data/lib/indocker/indocker_helper.rb +9 -0
  62. data/lib/indocker/network.rb +12 -0
  63. data/lib/indocker/network_helper.rb +7 -0
  64. data/lib/indocker/registries/abstract.rb +17 -0
  65. data/lib/indocker/registries/local.rb +5 -0
  66. data/lib/indocker/registries/remote.rb +12 -0
  67. data/lib/indocker/repositories/abstract.rb +25 -0
  68. data/lib/indocker/repositories/clonner.rb +17 -0
  69. data/lib/indocker/repositories/git.rb +24 -0
  70. data/lib/indocker/repositories/local.rb +20 -0
  71. data/lib/indocker/repositories/no_sync.rb +20 -0
  72. data/lib/indocker/rsync.rb +52 -0
  73. data/lib/indocker/server.rb +20 -0
  74. data/lib/indocker/server_pool.rb +30 -0
  75. data/lib/indocker/shell.rb +60 -0
  76. data/lib/indocker/ssh_result_logger.rb +18 -0
  77. data/lib/indocker/ssh_session.rb +92 -0
  78. data/lib/indocker/version.rb +1 -1
  79. data/lib/indocker/volume_helper.rb +7 -0
  80. data/lib/indocker/volumes/external.rb +8 -0
  81. data/lib/indocker/volumes/local.rb +9 -0
  82. data/lib/indocker/volumes/repository.rb +9 -0
  83. metadata +107 -222
  84. data/bin/indocker +0 -9
  85. data/lib/indocker/application_initializer.rb +0 -19
  86. data/lib/indocker/cli.rb +0 -27
  87. data/lib/indocker/configs/config.rb +0 -147
  88. data/lib/indocker/configs/config_factory.rb +0 -37
  89. data/lib/indocker/configs/config_initializer.rb +0 -9
  90. data/lib/indocker/configs/locator.rb +0 -23
  91. data/lib/indocker/container/container_builder.rb +0 -29
  92. data/lib/indocker/container/container_directives_runner.rb +0 -54
  93. data/lib/indocker/container/container_dsl.rb +0 -83
  94. data/lib/indocker/container/container_evaluator.rb +0 -13
  95. data/lib/indocker/container/container_inspector.rb +0 -26
  96. data/lib/indocker/container/container_manager.rb +0 -122
  97. data/lib/indocker/container/container_metadata.rb +0 -112
  98. data/lib/indocker/container/container_metadata_factory.rb +0 -30
  99. data/lib/indocker/container/container_metadata_repository.rb +0 -27
  100. data/lib/indocker/directives/base.rb +0 -17
  101. data/lib/indocker/directives/container_directives/base.rb +0 -23
  102. data/lib/indocker/directives/container_directives/cmd.rb +0 -7
  103. data/lib/indocker/directives/container_directives/depends_on.rb +0 -7
  104. data/lib/indocker/directives/container_directives/env.rb +0 -7
  105. data/lib/indocker/directives/container_directives/env_file.rb +0 -7
  106. data/lib/indocker/directives/container_directives/expose.rb +0 -7
  107. data/lib/indocker/directives/container_directives/from.rb +0 -14
  108. data/lib/indocker/directives/container_directives/network.rb +0 -12
  109. data/lib/indocker/directives/container_directives/ports.rb +0 -15
  110. data/lib/indocker/directives/container_directives/ready.rb +0 -16
  111. data/lib/indocker/directives/container_directives/volume.rb +0 -23
  112. data/lib/indocker/directives/image_directives/base.rb +0 -27
  113. data/lib/indocker/directives/image_directives/cmd.rb +0 -19
  114. data/lib/indocker/directives/image_directives/copy.rb +0 -32
  115. data/lib/indocker/directives/image_directives/docker_cp.rb +0 -20
  116. data/lib/indocker/directives/image_directives/entrypoint.rb +0 -19
  117. data/lib/indocker/directives/image_directives/env.rb +0 -9
  118. data/lib/indocker/directives/image_directives/env_file.rb +0 -19
  119. data/lib/indocker/directives/image_directives/expose.rb +0 -9
  120. data/lib/indocker/directives/image_directives/from.rb +0 -36
  121. data/lib/indocker/directives/image_directives/registry.rb +0 -30
  122. data/lib/indocker/directives/image_directives/run.rb +0 -17
  123. data/lib/indocker/directives/image_directives/workdir.rb +0 -9
  124. data/lib/indocker/directives/partial.rb +0 -21
  125. data/lib/indocker/docker_api/container_config.rb +0 -121
  126. data/lib/indocker/docker_api/docker_api.rb +0 -207
  127. data/lib/indocker/dsl_context.rb +0 -21
  128. data/lib/indocker/envs/env_metadata.rb +0 -39
  129. data/lib/indocker/envs/loader.rb +0 -19
  130. data/lib/indocker/errors.rb +0 -21
  131. data/lib/indocker/git/git_api.rb +0 -32
  132. data/lib/indocker/git/git_helper.rb +0 -34
  133. data/lib/indocker/git/git_service.rb +0 -21
  134. data/lib/indocker/handlers/container_run.rb +0 -20
  135. data/lib/indocker/handlers/container_stop.rb +0 -17
  136. data/lib/indocker/handlers/performable.rb +0 -22
  137. data/lib/indocker/image/image_builder.rb +0 -54
  138. data/lib/indocker/image/image_dependencies_manager.rb +0 -47
  139. data/lib/indocker/image/image_directives_runner.rb +0 -99
  140. data/lib/indocker/image/image_dockerfile_builder.rb +0 -24
  141. data/lib/indocker/image/image_dsl.rb +0 -89
  142. data/lib/indocker/image/image_evaluator.rb +0 -21
  143. data/lib/indocker/image/image_helper.rb +0 -9
  144. data/lib/indocker/image/image_metadata.rb +0 -50
  145. data/lib/indocker/image/image_metadata_factory.rb +0 -31
  146. data/lib/indocker/image/image_metadata_repository.rb +0 -29
  147. data/lib/indocker/networks/network_metadata.rb +0 -9
  148. data/lib/indocker/networks/network_metadata_factory.rb +0 -9
  149. data/lib/indocker/networks/network_metadata_repository.rb +0 -34
  150. data/lib/indocker/partial/partial_metadata.rb +0 -8
  151. data/lib/indocker/partial/partial_metadata_repository.rb +0 -26
  152. data/lib/indocker/registry/registry_api.rb +0 -46
  153. data/lib/indocker/registry/registry_helper.rb +0 -20
  154. data/lib/indocker/registry/registry_service.rb +0 -28
  155. data/lib/indocker/utils/ioc_container.rb +0 -17
  156. data/lib/indocker/utils/logger.rb +0 -62
  157. data/lib/indocker/utils/logger_factory.rb +0 -13
  158. data/lib/indocker/utils/registry_authenticator.rb +0 -19
  159. data/lib/indocker/utils/render_namespace.rb +0 -11
  160. data/lib/indocker/utils/render_util.rb +0 -15
  161. data/lib/indocker/utils/string_utils.rb +0 -11
  162. data/lib/indocker/utils/tar_helper.rb +0 -40
  163. data/lib/indocker/utils/test_logger_factory.rb +0 -9
  164. data/lib/indocker/volumes/volume_metadata.rb +0 -9
  165. data/lib/indocker/volumes/volume_metadata_factory.rb +0 -9
  166. data/lib/indocker/volumes/volume_metadata_repository.rb +0 -34
  167. data/spec/example/.indocker/config.rb +0 -30
  168. data/spec/example/.indocker/images_and_containers.rb +0 -25
  169. data/spec/example/assets/index.css +0 -1
  170. data/spec/example/assets/index.js +0 -1
  171. data/spec/fixtures/spec.env +0 -2
  172. data/spec/indocker/configs/config_factory_spec.rb +0 -18
  173. data/spec/indocker/configs/config_spec.rb +0 -88
  174. data/spec/indocker/container/container_builder_spec.rb +0 -67
  175. data/spec/indocker/container/container_manager_spec.rb +0 -278
  176. data/spec/indocker/docker_api/container_config_spec.rb +0 -64
  177. data/spec/indocker/docker_api/docker_api_spec.rb +0 -112
  178. data/spec/indocker/handlers/container_run_spec.rb +0 -60
  179. data/spec/indocker/image/image_builder_spec.rb +0 -153
  180. data/spec/indocker/image/image_directives_runner_spec.rb +0 -141
  181. data/spec/indocker/image/image_dockerfile_builder_spec.rb +0 -25
  182. data/spec/indocker/image/image_evaluator_spec.rb +0 -85
  183. data/spec/spec_helper.rb +0 -68
@@ -0,0 +1,126 @@
1
+ require 'digest'
2
+ require 'fileutils'
3
+
4
+ class Indocker::DeployContext
5
+ attr_reader :server, :session
6
+
7
+ def initialize(logger:, configuration:, server:)
8
+ @logger = logger
9
+ @configuration = configuration
10
+ @server = server
11
+ @restart_policy = Indocker::Containers::RestartPolicy.new(configuration, logger)
12
+
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
21
+ end
22
+
23
+ def exec!(command)
24
+ @session.exec!(command)
25
+ end
26
+
27
+ def close_session
28
+ @session.close if @session
29
+ end
30
+
31
+ def set_busy(flag)
32
+ @busy = !!flag
33
+ end
34
+
35
+ def busy?
36
+ !!@busy
37
+ end
38
+
39
+ def deploy(container, force_restart)
40
+ @logger.info("Deploying container: #{container.name.to_s.green}")
41
+ @logger.debug("Deploy dir: #{Indocker.deploy_dir}")
42
+
43
+ Indocker::Docker.pull(container.image.registry_url) if !container.image.registry.is_local?
44
+
45
+ container.networks.each do |network|
46
+ Indocker::Docker.create_network(
47
+ Indocker::NetworkHelper.name(@configuration.name, network)
48
+ )
49
+ end
50
+
51
+ container.volumes.each do |volume|
52
+ if volume.is_a?(Indocker::Volumes::External)
53
+ Indocker::Docker.create_volume(
54
+ Indocker::VolumeHelper.name(@configuration.name, volume)
55
+ )
56
+ end
57
+ end
58
+
59
+ container.get_start_option(:scale).times do |number|
60
+ arg_list = Indocker::DockerRunArgs
61
+ .get(container, @configuration, number)
62
+ .join(' ')
63
+
64
+ hostname = Indocker::ContainerHelper.hostname(@configuration.name, container, number)
65
+
66
+ # timestamp generation
67
+ run_cmd = Indocker::Docker.run_command(container.image.registry_url, arg_list, container.start_command, container.get_start_option(:service_args))
68
+
69
+ env_files = container.get_start_option(:env_files, default: [])
70
+ .map { |env_file|
71
+ env_file = @configuration.env_files.fetch(env_file)
72
+ File.read(Indocker::EnvFileHelper.path(env_file))
73
+ }
74
+ .join
75
+
76
+ image_id = Indocker::Docker.image_id(container.image.registry_url)
77
+ timestamp = Digest::MD5.hexdigest(run_cmd + image_id.to_s + env_files)
78
+
79
+ binary_path = File.join(File.expand_path(Indocker.deploy_dir), 'bin')
80
+ FileUtils.mkdir_p(binary_path)
81
+
82
+ binary_path = File.join(binary_path, hostname)
83
+
84
+ File.open(binary_path, 'w') { |f|
85
+ f.write("#!/bin/bash\n\n")
86
+ f.write(run_cmd)
87
+ }
88
+
89
+ FileUtils.chmod('+x', binary_path)
90
+
91
+ container_id = Indocker::Docker.container_id_by_name(hostname)
92
+
93
+ if !container_id || @restart_policy.restart?(container, timestamp) || force_restart
94
+ if container.before_start_proc
95
+ container.before_start_proc.call(container, number)
96
+ end
97
+
98
+ if container_id
99
+ Indocker::Docker.stop(hostname, skip_errors: true)
100
+ else
101
+ Indocker::Docker.rm(hostname, skip_errors: true)
102
+ end
103
+
104
+ Indocker::Docker.run(container.image.registry_url, arg_list, container.start_command, container.get_start_option(:service_args))
105
+
106
+ if container.after_start_proc
107
+ container.after_start_proc.call(container, number)
108
+ end
109
+
110
+ @restart_policy.update(container, timestamp)
111
+ else
112
+ @logger.info("Skipping restart for container #{container.name.to_s.green} as no changes were found")
113
+
114
+ if !container_id
115
+ @restart_policy.update(container, timestamp)
116
+ end
117
+ end
118
+
119
+ if container.after_deploy_proc
120
+ container.after_deploy_proc.call(container, number)
121
+ end
122
+ end
123
+
124
+ nil
125
+ end
126
+ end
@@ -0,0 +1,121 @@
1
+ class Indocker::DeploymentChecker
2
+ def initialize(debug_logger, output_logger = nil)
3
+ @debug_logger = debug_logger
4
+
5
+ if output_logger
6
+ @logger = output_logger
7
+ else
8
+ @logger = Logger.new(STDOUT)
9
+ @logger.formatter = debug_logger.formatter
10
+ end
11
+ end
12
+
13
+ def run(configuration:, servers:, only_containers: [])
14
+ server_list = configuration.servers.map(&:name)
15
+
16
+ server_list = servers.map do |server_name|
17
+ server = configuration.servers.detect { |s| s.name == server_name }
18
+
19
+ if !server
20
+ @logger.error("Invalid server name specified :#{server_name} for configuration :#{configuration.name}")
21
+ exit 1
22
+ end
23
+
24
+ server
25
+ end
26
+
27
+ if server_list.empty?
28
+ server_list = configuration.servers
29
+ end
30
+
31
+ server_list = server_list.sort_by(&:name)
32
+
33
+ @logger.info("Following servers will be checked:")
34
+
35
+ server_list.each do |server|
36
+ @logger.info(" - #{server.name}")
37
+ end
38
+
39
+ names_by_server = {}
40
+
41
+ server_list.each do |server|
42
+ names_by_server[server.name] = []
43
+ end
44
+
45
+ containers_by_server = Indocker
46
+ .configuration
47
+ .containers
48
+ .select{ |container| only_containers.empty? || only_containers.include?(container.name) }
49
+ .map do |container|
50
+ (container.get_start_option(:scale) || 1).times do |number|
51
+ container.servers.each do |server|
52
+ names_by_server[server.name] << Indocker::ContainerHelper.hostname(configuration.name, container, number)
53
+ end
54
+ end
55
+ end
56
+
57
+ total_invalid_containers = []
58
+ total_missing_containers = []
59
+
60
+ server_list.each do |server|
61
+ session = Indocker::SshSession.new(
62
+ host: server.host,
63
+ user: server.user,
64
+ port: server.port,
65
+ logger: @debug_logger
66
+ )
67
+
68
+ result = session.exec!('docker ps --filter="status=running" --format="{{.Names}}"')
69
+
70
+ if !result.success?
71
+ @logger.warn(result.stdout_data)
72
+ @logger.warn(result.stderr_data)
73
+ exit 1
74
+ end
75
+
76
+ names_list = result
77
+ .stdout_data
78
+ .strip
79
+ .split("\n")
80
+
81
+ invalid_containers = (names_list - names_by_server[server.name]).uniq
82
+
83
+ total_invalid_containers += invalid_containers
84
+
85
+ if !invalid_containers.empty?
86
+ @logger.warn("EXTRA containers for server #{server.name.to_s.yellow}:")
87
+
88
+ invalid_containers.each do |name|
89
+ @logger.warn(" - #{name}")
90
+ end
91
+ end
92
+
93
+ missing_containers = (names_by_server[server.name] - names_list).uniq
94
+ missing_containers = missing_containers.select do |name|
95
+ !(name.include?('migrations') || name.include?('gems_installer'))
96
+ end
97
+
98
+ total_missing_containers += missing_containers
99
+
100
+ if !missing_containers.empty?
101
+ @logger.warn("MISSING CONTAINERS for server #{server.name.to_s.yellow}:")
102
+
103
+ missing_containers.each do |name|
104
+ @logger.warn(" - #{name}")
105
+ end
106
+ end
107
+ end
108
+
109
+ { missing_containers: total_missing_containers, invalid_containers: total_invalid_containers }
110
+ end
111
+
112
+ def launched?(container_name, configuration:, servers:)
113
+ container = Indocker.containers.detect { |c| c.name == container_name.to_sym }
114
+ hostnames = (container.get_start_option(:scale) || 1).times.map do |number|
115
+ Indocker::ContainerHelper.hostname(configuration.name, container, number)
116
+ end
117
+
118
+ result = run(configuration: configuration, servers: servers, only_containers: [container.name])
119
+ result[:missing_containers].empty?
120
+ end
121
+ end
@@ -0,0 +1,495 @@
1
+ require 'thread'
2
+
3
+ class Indocker::DeploymentProgress
4
+ def initialize(logger)
5
+ @logger = logger
6
+
7
+ if logger
8
+ @logger.formatter = Proc.new do |severity, datetime, progname, msg|
9
+ "#{msg}\n"
10
+ end
11
+ end
12
+
13
+ @progress = Hash.new(:waiting)
14
+ @semaphore = Mutex.new
15
+
16
+ @synced_binaries = {
17
+ # Structure:
18
+ # server => {
19
+ # start: time,
20
+ # finish: time,
21
+ # state: (:waiting|:in_progress|:finished)
22
+ # }
23
+ }
24
+
25
+ @synced_env_files = {
26
+ # Structure:
27
+ # env_file => {
28
+ # server => {
29
+ # start: time,
30
+ # finish: time,
31
+ # state: (:waiting|:in_progress|:finished)
32
+ # }
33
+ # }
34
+ }
35
+
36
+ @synced_artifacts = {
37
+ # Structure:
38
+ # artifact => {
39
+ # server => {
40
+ # start: time,
41
+ # finish: time,
42
+ # state: (:waiting|:in_progress|:finished)
43
+ # }
44
+ # }
45
+ }
46
+
47
+ @synced_repositories = {
48
+ # Structure:
49
+ # repository => {
50
+ # server => {
51
+ # start: time,
52
+ # finish: time,
53
+ # state: (:waiting|:in_progress|:finished)
54
+ # }
55
+ # }
56
+ }
57
+
58
+ @deployed_containers = {
59
+ # Structure:
60
+ # container => {
61
+ # server => {
62
+ # build_start: time,
63
+ # build_finish: time,
64
+ # deploy_start: time,
65
+ # deploy_finish: time,
66
+ # state: (:waiting|:building|:waiting_deployment|:deploying|:finished)
67
+ # }
68
+ # }
69
+ }
70
+ end
71
+
72
+ def setup(binaries_servers:, build_servers:, deploy_servers:, env_files:, artifact_servers:,
73
+ repositories:, force_restart:, skip_build:, containers:)
74
+ @force_restart = force_restart
75
+ @skip_build = skip_build
76
+
77
+ binaries_servers.each do |server|
78
+ @synced_binaries[server] = {
79
+ start: nil,
80
+ finish: nil,
81
+ state: :waiting
82
+ }
83
+ end
84
+
85
+ repositories.each do |repository|
86
+ @synced_repositories[repository] = {}
87
+
88
+ build_servers.each do |server|
89
+ @synced_repositories[repository][server] = {
90
+ start: nil,
91
+ finish: nil,
92
+ state: :waiting
93
+ }
94
+ end
95
+ end
96
+
97
+ env_files.each do |env_file|
98
+ @synced_env_files[env_file] = {}
99
+
100
+ deploy_servers.each do |server|
101
+ @synced_env_files[env_file][server] = {
102
+ start: nil,
103
+ finish: nil,
104
+ state: :waiting
105
+ }
106
+ end
107
+ end
108
+
109
+ artifact_servers.each do |artifact, servers|
110
+ @synced_artifacts[artifact] = {}
111
+
112
+ servers.each do |server|
113
+ @synced_artifacts[artifact][server] = {
114
+ start: nil,
115
+ finish: nil,
116
+ state: :waiting
117
+ }
118
+ end
119
+ end
120
+
121
+ @containers = containers
122
+
123
+ containers.each do |container|
124
+ @deployed_containers[container] = {}
125
+
126
+ container.servers.each do |server|
127
+ @deployed_containers[container][server] = {
128
+ build_start: nil,
129
+ build_finish: nil,
130
+ deploy_start: nil,
131
+ deploy_finish: nil,
132
+ state: :waiting
133
+ }
134
+ end
135
+ end
136
+
137
+ log
138
+ end
139
+
140
+ def start_syncing_binaries(server)
141
+ @semaphore.synchronize do
142
+ @synced_binaries[server][:start] = Time.now
143
+ @synced_binaries[server][:state] = :in_progress
144
+ log
145
+ end
146
+ end
147
+
148
+ def finish_syncing_binaries(server)
149
+ @semaphore.synchronize do
150
+ @synced_binaries[server][:finish] = Time.now
151
+ @synced_binaries[server][:state] = :finished
152
+ log
153
+ end
154
+ end
155
+
156
+ def start_syncing_env_file(server, env_file)
157
+ @semaphore.synchronize do
158
+ @synced_env_files[env_file][server][:start] = Time.now
159
+ log
160
+ end
161
+ end
162
+
163
+ def finish_syncing_env_file(server, env_file)
164
+ @semaphore.synchronize do
165
+ @synced_env_files[env_file][server][:finish] = Time.now
166
+ @synced_env_files[env_file][server][:state] = :finished
167
+ log
168
+ end
169
+ end
170
+
171
+ def start_syncing_artifact(server, artifact)
172
+ @semaphore.synchronize do
173
+ @synced_artifacts[artifact][server][:start] = Time.now
174
+ log
175
+ end
176
+ end
177
+
178
+ def finish_syncing_artifact(server, artifact)
179
+ @semaphore.synchronize do
180
+ @synced_artifacts[artifact][server][:finish] = Time.now
181
+ @synced_artifacts[artifact][server][:state] = :finished
182
+ log
183
+ end
184
+ end
185
+
186
+ def start_syncing_repository(server, repository)
187
+ @semaphore.synchronize do
188
+ @synced_repositories[repository][server][:start] = Time.now
189
+ log
190
+ end
191
+ end
192
+
193
+ def finish_syncing_repository(server, repository)
194
+ @semaphore.synchronize do
195
+ @synced_repositories[repository][server][:finish] = Time.now
196
+ @synced_repositories[repository][server][:state] = :finished
197
+ log
198
+ end
199
+ end
200
+
201
+ def start_building_container(container)
202
+ @semaphore.synchronize do
203
+ time = Time.now
204
+
205
+ @deployed_containers[container].each do |server, data|
206
+ next if data[:build_start]
207
+ data[:build_start] = time
208
+ data[:state] = :building
209
+ end
210
+
211
+ log
212
+ end
213
+ end
214
+
215
+ def finish_building_container(container)
216
+ @semaphore.synchronize do
217
+ time = Time.now
218
+
219
+ @deployed_containers[container].each do |server, data|
220
+ next if data[:build_finish]
221
+ data[:build_finish] = time
222
+ data[:state] = :waiting_deployment
223
+ end
224
+
225
+ log
226
+ end
227
+ end
228
+
229
+ def start_deploying_container(container, server)
230
+ @semaphore.synchronize do
231
+ @deployed_containers[container][server][:deploy_start] = Time.now
232
+ @deployed_containers[container][server][:state] = :deploying
233
+ log
234
+ end
235
+ end
236
+
237
+ def finish_deploying_container(container, server)
238
+ @semaphore.synchronize do
239
+ @deployed_containers[container][server][:deploy_finish] = Time.now
240
+ @deployed_containers[container][server][:state] = :finished
241
+ log
242
+ end
243
+ end
244
+
245
+ def log
246
+ return if !@logger
247
+ system("clear")
248
+
249
+ if @skip_build
250
+ @logger.info("Warning: Image build is skipped for all containers".purple)
251
+ end
252
+
253
+ if @force_restart
254
+ @logger.info("Warning: All containers will be force restarted".purple)
255
+ end
256
+
257
+ # BINARIES formatter
258
+ synced_binaries_servers = []
259
+ not_synced_binaries_servers = []
260
+
261
+ @synced_binaries.each do |server, data|
262
+ if data[:state] == :finished
263
+ synced_binaries_servers << server
264
+ else
265
+ not_synced_binaries_servers << server
266
+ end
267
+ end
268
+
269
+ if !synced_binaries_servers.empty?
270
+ @logger.info("Binaries synced:".green)
271
+
272
+ synced_binaries_servers.each do |server|
273
+ data = @synced_binaries[server]
274
+ total = ", total: #{(data[:finish] - data[:start]).round}s" if data[:finish]
275
+ @logger.info(" - #{server.name.to_s.yellow}#{total}")
276
+ end
277
+ end
278
+
279
+ if !not_synced_binaries_servers.empty?
280
+ @logger.info("Binaries syncing:".green)
281
+
282
+ not_synced_binaries_servers.each do |server|
283
+ data = @synced_binaries[server]
284
+ @logger.info(" - #{server.name.to_s.cyan} (#{data[:state]}...)")
285
+ end
286
+ end
287
+
288
+ # ENV FILES formatter
289
+ synced_env_files = []
290
+ not_synced_env_files = []
291
+
292
+ @synced_env_files.each do |env_file, server_info|
293
+ server_info.each do |server, data|
294
+ if data[:state] == :finished
295
+ if !synced_env_files.include?(env_file)
296
+ synced_env_files << env_file
297
+ end
298
+ else
299
+ if !not_synced_env_files.include?(env_file)
300
+ not_synced_env_files << env_file
301
+ end
302
+ end
303
+ end
304
+ end
305
+
306
+ if !synced_env_files.empty?
307
+ @logger.info("ENV files synced:".green)
308
+
309
+ synced_env_files.each do |env_file|
310
+ servers_data = @synced_env_files[env_file]
311
+
312
+ servers_data.each do |server, data|
313
+ next if data[:state] != :finished
314
+ total = ", total: #{(data[:finish] - data[:start]).round}s" if data[:finish]
315
+ @logger.info(" - #{env_file.to_s.yellow}, server: #{server.name}#{total}")
316
+ end
317
+ end
318
+ end
319
+
320
+ if !not_synced_env_files.empty?
321
+ @logger.info("ENV files syncing:".green)
322
+
323
+ not_synced_env_files.each do |env_file|
324
+ servers_data = @synced_env_files[env_file]
325
+
326
+ servers_data.each do |server, data|
327
+ next if data[:state] == :finished
328
+ @logger.info(" - #{env_file.to_s.cyan}, server: #{server.name} (#{data[:state]}...)")
329
+ end
330
+ end
331
+ end
332
+
333
+ # Artifacts formatter
334
+ synced_artifact = []
335
+ not_synced_artifact = []
336
+
337
+ @synced_artifacts.each do |artifact, server_info|
338
+ server_info.each do |server, data|
339
+ if data[:state] == :finished
340
+ if !synced_artifact.include?(artifact)
341
+ synced_artifact << artifact
342
+ end
343
+ else
344
+ if !not_synced_artifact.include?(artifact)
345
+ not_synced_artifact << artifact
346
+ end
347
+ end
348
+ end
349
+ end
350
+
351
+ if !synced_artifact.empty?
352
+ @logger.info("Artifacts synced:".green)
353
+
354
+ synced_artifact.each do |artifact|
355
+ servers_data = @synced_artifacts[artifact]
356
+
357
+ servers_data.each do |server, data|
358
+ next if data[:state] != :finished
359
+ total = ", total: #{(data[:finish] - data[:start]).round}s" if data[:finish]
360
+ @logger.info(" - #{artifact.name.to_s.yellow}, server: #{server.name}#{total}")
361
+ end
362
+ end
363
+ end
364
+
365
+ if !not_synced_artifact.empty?
366
+ @logger.info("Artifacts syncing:".green)
367
+
368
+ not_synced_artifact.each do |artifact|
369
+ servers_data = @synced_artifacts[artifact]
370
+
371
+ servers_data.each do |server, data|
372
+ next if data[:state] == :finished
373
+ @logger.info(" - #{artifact.name.to_s.cyan}, server: #{server.name} (#{data[:state]}...)")
374
+ end
375
+ end
376
+ end
377
+
378
+ # REPOSITORIES formatter
379
+ synced_repositories = []
380
+ not_synced_repositories = []
381
+
382
+ @synced_repositories.each do |repository, server_info|
383
+ server_info.each do |server, data|
384
+ if data[:state] == :finished
385
+ if !synced_repositories.include?(repository)
386
+ synced_repositories << repository
387
+ end
388
+ else
389
+ if !not_synced_repositories.include?(repository)
390
+ not_synced_repositories << repository
391
+ end
392
+ end
393
+ end
394
+ end
395
+
396
+ if !synced_repositories.empty?
397
+ @logger.info("Repositories synced:".green)
398
+
399
+ synced_repositories.each do |repository|
400
+ servers_data = @synced_repositories[repository]
401
+
402
+ servers_data.each do |server, data|
403
+ next if data[:state] != :finished
404
+ total = ", total: #{(data[:finish] - data[:start]).round}s" if data[:finish]
405
+ @logger.info(" - #{repository.to_s.yellow}, server: #{server.name}#{total}")
406
+ end
407
+ end
408
+ end
409
+
410
+ if !not_synced_repositories.empty?
411
+ @logger.info("Repositories syncing:".green)
412
+
413
+ not_synced_repositories.each do |repository|
414
+ servers_data = @synced_repositories[repository]
415
+
416
+ servers_data.each do |server, data|
417
+ next if data[:state] == :finished
418
+ @logger.info(" - #{repository.to_s.cyan}, server: #{server.name} (#{data[:state]}...)")
419
+ end
420
+ end
421
+ end
422
+
423
+ # Containers formatter
424
+ deployed_containers = []
425
+ not_deployed_containers = []
426
+
427
+ @deployed_containers.each do |container, server_info|
428
+ server_info.each do |server, data|
429
+ if data[:state] == :finished
430
+ if !deployed_containers.include?(container)
431
+ deployed_containers << container
432
+ end
433
+ else
434
+ if !not_deployed_containers.include?(container)
435
+ not_deployed_containers << container
436
+ end
437
+ end
438
+ end
439
+ end
440
+
441
+ if !deployed_containers.empty?
442
+ @logger.info("Deployed containers:".green)
443
+
444
+ deployed_containers = deployed_containers
445
+ .sort_by { |container|
446
+ @deployed_containers[container]
447
+ .map { |server, data| data[:deploy_finish] }
448
+ .reject(&:nil?)
449
+ .sort
450
+ .last
451
+ .to_i
452
+ }
453
+
454
+ deployed_containers.each do |container|
455
+ servers_data = @deployed_containers[container]
456
+
457
+ servers_data.each do |server, data|
458
+ next if data[:state] != :finished
459
+ total = ", total: #{(data[:deploy_finish] - data[:build_start]).round}s"
460
+ build = ", build: #{(data[:build_finish] - data[:build_start]).round}s"
461
+ deploy = ", deploy: #{(data[:deploy_finish] - data[:deploy_start]).round}s"
462
+ @logger.info(" - #{container.name.to_s.yellow}, server: #{server.name}#{build}#{deploy}#{total}")
463
+ end
464
+ end
465
+ end
466
+
467
+ if !not_deployed_containers.empty?
468
+ @logger.info("To be deployed containers:".green)
469
+
470
+ not_deployed_containers.each do |container|
471
+ servers_data = @deployed_containers[container]
472
+
473
+ servers_data.each do |server, data|
474
+ next if data[:state] == :finished
475
+
476
+ name = container.name.to_s
477
+
478
+ name = if data[:state] == :waiting
479
+ name
480
+ else
481
+ name.cyan
482
+ end
483
+
484
+ @logger.info(" - #{name}, server: #{server.name} (#{data[:state]}...)")
485
+ end
486
+ end
487
+ end
488
+ end
489
+
490
+ private
491
+
492
+ def format_time(time)
493
+ time.strftime("%H:%M:%S")
494
+ end
495
+ end