indocker 0.1.6 → 0.1.11
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.
- checksums.yaml +4 -4
- data/Gemfile +5 -0
- data/Gemfile.lock +10 -4
- data/README.md +13 -2
- data/example/indocker/bin/deploy +19 -13
- data/example/indocker/bounded_contexts/shared/bad_container_build/Dockerfile +3 -0
- data/example/indocker/bounded_contexts/shared/bad_container_build/container.rb +5 -0
- data/example/indocker/bounded_contexts/shared/bad_container_build/image.rb +3 -0
- data/example/indocker/bounded_contexts/shared/bad_container_start/Dockerfile +8 -0
- data/example/indocker/bounded_contexts/shared/bad_container_start/build_context/bin/run +3 -0
- data/example/indocker/bounded_contexts/shared/bad_container_start/container.rb +5 -0
- data/example/indocker/bounded_contexts/shared/bad_container_start/image.rb +3 -0
- data/example/indocker/bounded_contexts/shared/good_container/Dockerfile +4 -0
- data/example/indocker/bounded_contexts/shared/good_container/container.rb +5 -0
- data/example/indocker/bounded_contexts/shared/good_container/image.rb +3 -0
- data/example/indocker/configurations/external.rb +18 -0
- data/example/indocker/infrastructure/build_servers.rb +11 -0
- data/example/indocker/infrastructure/servers.rb +11 -0
- data/example/indocker/setup.rb +1 -1
- data/example/spec/indocker_spec.rb +39 -0
- data/example/spec/spec_helper.rb +39 -0
- data/indocker.gemspec +1 -1
- data/lib/indocker.rb +37 -57
- data/lib/indocker/build_context.rb +13 -12
- data/lib/indocker/build_context_pool.rb +5 -1
- data/lib/indocker/configuration_deployer.rb +125 -93
- data/lib/indocker/container_deployer.rb +17 -7
- data/lib/indocker/context_args.rb +2 -0
- data/lib/indocker/deploy_context.rb +10 -8
- data/lib/indocker/deployment_policy.rb +22 -0
- data/lib/indocker/deployment_progress.rb +7 -2
- data/lib/indocker/images_compiler.rb +1 -1
- data/lib/indocker/logger_factory.rb +37 -0
- data/lib/indocker/server_pool.rb +9 -1
- data/lib/indocker/ssh_session.rb +21 -10
- data/lib/indocker/version.rb +1 -1
- metadata +19 -5
- data/lib/indocker/ssh_result_logger.rb +0 -18
@@ -8,17 +8,18 @@ class Indocker::BuildContext
|
|
8
8
|
@logger = logger
|
9
9
|
@helper = Indocker::BuildContextHelper.new(@configuration, @build_server)
|
10
10
|
@server = build_server
|
11
|
+
@compiled_images = Hash.new(false)
|
12
|
+
end
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
host: build_server.host,
|
15
|
-
user: build_server.user,
|
16
|
-
port: build_server.port,
|
17
|
-
logger: @logger
|
18
|
-
)
|
19
|
-
end
|
14
|
+
def create_session!
|
15
|
+
return unless @server
|
20
16
|
|
21
|
-
@
|
17
|
+
@session = Indocker::SshSession.new(
|
18
|
+
host: @server.host,
|
19
|
+
user: @server.user,
|
20
|
+
port: @server.port,
|
21
|
+
logger: @logger
|
22
|
+
)
|
22
23
|
end
|
23
24
|
|
24
25
|
def exec!(command)
|
@@ -69,10 +70,10 @@ class Indocker::BuildContext
|
|
69
70
|
build_args = args.join(' ')
|
70
71
|
|
71
72
|
res = Indocker::Docker.build(image.local_registry_url, build_args)
|
72
|
-
|
73
|
+
|
73
74
|
if res.exit_status != 0
|
74
|
-
|
75
|
-
|
75
|
+
puts "image compilation :#{image.name} failed"
|
76
|
+
puts res.stdout
|
76
77
|
exit 1
|
77
78
|
end
|
78
79
|
|
@@ -7,11 +7,15 @@ class Indocker::BuildContextPool
|
|
7
7
|
Indocker::BuildContext.new(
|
8
8
|
logger: @logger,
|
9
9
|
configuration: configuration,
|
10
|
-
build_server: build_server
|
10
|
+
build_server: build_server
|
11
11
|
)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
def create_sessions!
|
16
|
+
@contexts.each(&:create_session!)
|
17
|
+
end
|
18
|
+
|
15
19
|
def get
|
16
20
|
context = nil
|
17
21
|
|
@@ -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 =
|
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
|
-
|
21
|
-
|
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
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
37
|
+
run!(configuration: configuration, deployment_policy: deployment_policy)
|
38
|
+
end
|
56
39
|
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
-
|
70
|
-
|
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)
|
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
|
-
|
73
|
-
|
80
|
+
remote_operations = sync_indocker(servers)
|
81
|
+
wait_remote_operations(remote_operations)
|
74
82
|
|
75
|
-
|
76
|
-
|
83
|
+
remote_operations = sync_env_files(deploy_servers, configuration.env_files)
|
84
|
+
wait_remote_operations(remote_operations)
|
77
85
|
|
78
|
-
|
79
|
-
|
86
|
+
remote_operations = pull_repositories(clonner, build_servers, configuration.repositories)
|
87
|
+
wait_remote_operations(remote_operations)
|
80
88
|
|
81
|
-
|
89
|
+
remote_operations = sync_artifacts(clonner, configuration.artifact_servers)
|
90
|
+
wait_remote_operations(remote_operations)
|
82
91
|
|
83
|
-
|
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
|
-
|
88
|
-
|
89
|
-
|
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
|
-
|
93
|
-
|
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
|
115
|
-
configuration
|
116
|
-
|
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
|
|
@@ -270,24 +290,42 @@ class Indocker::ConfigurationDeployer
|
|
270
290
|
result = build_context
|
271
291
|
.session
|
272
292
|
.exec!(
|
273
|
-
"cd #{Indocker::IndockerHelper.indocker_dir} && ./bin/remote/compile -C #{Indocker.configuration_name} -i #{image.name} -s #{@logger.debug? ? '-d' : ''}"
|
293
|
+
"cd #{Indocker::IndockerHelper.indocker_dir} && ./bin/remote/compile -C #{Indocker.configuration_name} -i #{image.name} -s #{@logger.debug? ? '-d' : ''}",
|
294
|
+
on_stdout: proc { |data|
|
295
|
+
@logger.info("[compile] #{data}")
|
296
|
+
},
|
297
|
+
on_stderr: proc { |data|
|
298
|
+
@logger.error("[compile] #{data}")
|
299
|
+
}
|
274
300
|
)
|
275
301
|
end
|
276
302
|
|
277
|
-
|
278
|
-
.
|
279
|
-
|
280
|
-
|
281
|
-
|
303
|
+
if result.exit_code != 0
|
304
|
+
@global_logger.error("[compile] #{image.name.to_s.green} image compilation failed")
|
305
|
+
puts result.stdout_data
|
306
|
+
exit 1
|
307
|
+
end
|
282
308
|
|
283
309
|
@logger.info("Image compilation completed #{image.name.to_s.green}. Time taken: #{time}")
|
284
310
|
|
285
311
|
build_context.set_compiled(image)
|
286
312
|
end
|
287
313
|
|
288
|
-
def recursively_deploy_container(configuration, deployer, build_context_pool, container,
|
314
|
+
def recursively_deploy_container(configuration, deployer, build_context_pool, container,
|
315
|
+
containers, skip_build, skip_deploy, force_restart, skip_force_restart)
|
316
|
+
|
289
317
|
container.dependent_containers.each do |container|
|
290
|
-
recursively_deploy_container(
|
318
|
+
recursively_deploy_container(
|
319
|
+
configuration,
|
320
|
+
deployer,
|
321
|
+
build_context_pool,
|
322
|
+
container,
|
323
|
+
containers,
|
324
|
+
skip_build,
|
325
|
+
skip_deploy,
|
326
|
+
force_restart,
|
327
|
+
skip_force_restart
|
328
|
+
)
|
291
329
|
end
|
292
330
|
|
293
331
|
return if !containers.include?(container)
|
@@ -304,7 +342,9 @@ class Indocker::ConfigurationDeployer
|
|
304
342
|
|
305
343
|
@progress.finish_building_container(container)
|
306
344
|
|
307
|
-
|
345
|
+
if !skip_deploy
|
346
|
+
deployer.deploy(container, force_restart, skip_force_restart, @progress)
|
347
|
+
end
|
308
348
|
end
|
309
349
|
|
310
350
|
class RemoteOperation
|
@@ -319,7 +359,6 @@ class Indocker::ConfigurationDeployer
|
|
319
359
|
end
|
320
360
|
|
321
361
|
def pull_repositories(clonner, servers, repositories)
|
322
|
-
@logger.info("{timestamp}")
|
323
362
|
@logger.info("Clonning/pulling repositories")
|
324
363
|
|
325
364
|
remote_operations = []
|
@@ -372,7 +411,6 @@ class Indocker::ConfigurationDeployer
|
|
372
411
|
end
|
373
412
|
|
374
413
|
def sync_artifacts(clonner, artifact_servers)
|
375
|
-
@logger.info("{timestamp}")
|
376
414
|
@logger.info("Syncing git artifacts")
|
377
415
|
|
378
416
|
remote_operations = []
|
@@ -424,8 +462,6 @@ class Indocker::ConfigurationDeployer
|
|
424
462
|
redeploy_containers = configuration.containers.select {|c| c.redeploy_schedule}.uniq
|
425
463
|
return if redeploy_containers.empty?
|
426
464
|
|
427
|
-
@logger.info("{timestamp}")
|
428
|
-
|
429
465
|
deploy_user = "#{server.user}@#{server.host}"
|
430
466
|
crontab_filepath = Indocker.redeploy_crontab_path
|
431
467
|
|
@@ -450,8 +486,6 @@ class Indocker::ConfigurationDeployer
|
|
450
486
|
end
|
451
487
|
|
452
488
|
def sync_indocker(servers)
|
453
|
-
@logger.info("{timestamp}")
|
454
|
-
|
455
489
|
servers.map do |server|
|
456
490
|
@progress.start_syncing_binaries(server)
|
457
491
|
|
@@ -482,8 +516,6 @@ class Indocker::ConfigurationDeployer
|
|
482
516
|
end
|
483
517
|
|
484
518
|
def sync_env_files(servers, env_files)
|
485
|
-
@logger.info("{timestamp}")
|
486
|
-
|
487
519
|
remote_operations = []
|
488
520
|
|
489
521
|
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"
|
@@ -47,14 +50,21 @@ class Indocker::ContainerDeployer
|
|
47
50
|
result = deploy_context
|
48
51
|
.session
|
49
52
|
.exec!(
|
50
|
-
"cd #{Indocker::IndockerHelper.indocker_dir} && ./bin/remote/run -C #{Indocker.configuration_name} -c #{container.name} #{debug_options} #{command_output} #{force_restart_options}"
|
53
|
+
"cd #{Indocker::IndockerHelper.indocker_dir} && ./bin/remote/run -C #{Indocker.configuration_name} -c #{container.name} #{debug_options} #{command_output} #{force_restart_options}",
|
54
|
+
on_stdout: proc { |data|
|
55
|
+
@logger.info("[deploy] #{data}")
|
56
|
+
},
|
57
|
+
on_stderr: proc { |data|
|
58
|
+
@logger.error("[deploy] #{data}")
|
59
|
+
}
|
51
60
|
)
|
61
|
+
|
62
|
+
if result.exit_code != 0
|
63
|
+
@global_logger.error("[deploy] #{container.name.to_s.green} deployment for server #{server.name} failed")
|
64
|
+
puts result.stdout_data
|
65
|
+
exit 1
|
66
|
+
end
|
52
67
|
|
53
|
-
Indocker::SshResultLogger
|
54
|
-
.new(@logger)
|
55
|
-
.log(result, "#{container.name.to_s.green} deployment for server #{server.name} failed")
|
56
|
-
|
57
|
-
exit 1 if result.exit_code != 0
|
58
68
|
@logger.info("Container deployment to #{server.user}@#{server.host} finished: #{container.name.to_s.green}")
|
59
69
|
|
60
70
|
deploy_context.close_session
|