indocker 0.0.6 → 0.1.4

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 (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