indocker 0.1.9 → 0.1.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -0
- data/Gemfile +0 -1
- data/Gemfile.lock +10 -4
- data/example/indocker/bounded_contexts/shared/{container_failing_build → bad_container_build}/Dockerfile +0 -1
- data/example/indocker/bounded_contexts/shared/bad_container_build/container.rb +6 -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 +6 -0
- data/example/indocker/bounded_contexts/shared/bad_container_start/image.rb +3 -0
- data/example/indocker/bounded_contexts/shared/daemon_container/Dockerfile +4 -0
- data/example/indocker/bounded_contexts/shared/daemon_container/container.rb +6 -0
- data/example/indocker/bounded_contexts/shared/daemon_container/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 +6 -0
- data/example/indocker/bounded_contexts/shared/good_container/image.rb +3 -0
- data/example/indocker/bounded_contexts/shared/ruby/container.rb +2 -1
- data/example/indocker/configurations/external.rb +13 -2
- data/example/indocker/infrastructure/artifacts.rb +10 -0
- data/example/indocker/setup.rb +1 -0
- data/indocker.gemspec +2 -1
- data/lib/indocker.rb +24 -12
- data/lib/indocker/build_context.rb +6 -41
- data/lib/indocker/container_deployer.rb +12 -23
- data/lib/indocker/crontab_redeploy_rules_builder.rb +2 -1
- data/lib/indocker/deploy_context.rb +4 -32
- data/lib/indocker/docker_run_args.rb +2 -2
- data/lib/indocker/images/image_compiler.rb +0 -1
- data/lib/indocker/{configuration_deployer.rb → launchers/configuration_deployer.rb} +29 -30
- data/lib/indocker/{container_runner.rb → launchers/container_runner.rb} +2 -3
- data/lib/indocker/{images_compiler.rb → launchers/images_compiler.rb} +3 -3
- data/lib/indocker/{network.rb → networks/network.rb} +1 -1
- data/lib/indocker/{network_helper.rb → networks/network_helper.rb} +1 -1
- data/lib/indocker/server_pools/build_server_connection.rb +15 -0
- data/lib/indocker/server_pools/build_server_pool.rb +40 -0
- data/lib/indocker/server_pools/deploy_server_connection.rb +17 -0
- data/lib/indocker/server_pools/deploy_server_pool.rb +41 -0
- data/lib/indocker/server_pools/server_connection.rb +36 -0
- data/lib/indocker/ssh_session.rb +18 -9
- data/lib/indocker/version.rb +1 -1
- data/lib/indocker/{volume_helper.rb → volumes/volume_helper.rb} +1 -1
- metadata +44 -17
- data/example/indocker/bounded_contexts/shared/container_failing_build/container.rb +0 -5
- data/example/indocker/bounded_contexts/shared/container_failing_build/image.rb +0 -3
- data/example/spec/indocker_spec.rb +0 -31
- data/example/spec/spec_helper.rb +0 -39
- data/lib/indocker/build_context_pool.rb +0 -42
- data/lib/indocker/server_pool.rb +0 -38
@@ -2,42 +2,14 @@ require 'digest'
|
|
2
2
|
require 'fileutils'
|
3
3
|
|
4
4
|
class Indocker::DeployContext
|
5
|
-
attr_reader :
|
5
|
+
attr_reader :configuration, :logger
|
6
6
|
|
7
|
-
def initialize(logger:, configuration
|
7
|
+
def initialize(logger:, configuration:)
|
8
8
|
@logger = logger
|
9
9
|
@configuration = configuration
|
10
|
-
@server = server
|
11
10
|
@restart_policy = Indocker::Containers::RestartPolicy.new(configuration, logger)
|
12
11
|
end
|
13
12
|
|
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
|
-
)
|
23
|
-
end
|
24
|
-
|
25
|
-
def exec!(command)
|
26
|
-
@session.exec!(command)
|
27
|
-
end
|
28
|
-
|
29
|
-
def close_session
|
30
|
-
@session.close if @session
|
31
|
-
end
|
32
|
-
|
33
|
-
def set_busy(flag)
|
34
|
-
@busy = !!flag
|
35
|
-
end
|
36
|
-
|
37
|
-
def busy?
|
38
|
-
!!@busy
|
39
|
-
end
|
40
|
-
|
41
13
|
def deploy(container, force_restart)
|
42
14
|
@logger.info("Deploying container: #{container.name.to_s.green}")
|
43
15
|
@logger.debug("Deploy dir: #{Indocker.deploy_dir}")
|
@@ -46,14 +18,14 @@ class Indocker::DeployContext
|
|
46
18
|
|
47
19
|
container.networks.each do |network|
|
48
20
|
Indocker::Docker.create_network(
|
49
|
-
Indocker::NetworkHelper.name(@configuration.name, network)
|
21
|
+
Indocker::Networks::NetworkHelper.name(@configuration.name, network)
|
50
22
|
)
|
51
23
|
end
|
52
24
|
|
53
25
|
container.volumes.each do |volume|
|
54
26
|
if volume.is_a?(Indocker::Volumes::External)
|
55
27
|
Indocker::Docker.create_volume(
|
56
|
-
Indocker::VolumeHelper.name(@configuration.name, volume)
|
28
|
+
Indocker::Volumes::VolumeHelper.name(@configuration.name, volume)
|
57
29
|
)
|
58
30
|
end
|
59
31
|
end
|
@@ -159,7 +159,7 @@ class Indocker::DockerRunArgs
|
|
159
159
|
if volume.is_a?(Indocker::Volumes::Local)
|
160
160
|
args.push("-v #{volume.local_path}:#{volume.path}")
|
161
161
|
elsif volume.is_a?(Indocker::Volumes::External)
|
162
|
-
name = Indocker::VolumeHelper.name(configuration.name, volume)
|
162
|
+
name = Indocker::Volumes::VolumeHelper.name(configuration.name, volume)
|
163
163
|
args.push("-v #{name}:#{volume.path}")
|
164
164
|
elsif volume.is_a?(Indocker::Volumes::Repository)
|
165
165
|
repository = configuration.repositories.fetch(volume.repository_name) do
|
@@ -173,7 +173,7 @@ class Indocker::DockerRunArgs
|
|
173
173
|
end
|
174
174
|
|
175
175
|
container.networks.each do |network|
|
176
|
-
name = Indocker::NetworkHelper.name(configuration.name, network)
|
176
|
+
name = Indocker::Networks::NetworkHelper.name(configuration.name, network)
|
177
177
|
args.push("--network #{name}")
|
178
178
|
end
|
179
179
|
|
@@ -2,7 +2,7 @@ require 'timeout'
|
|
2
2
|
require 'benchmark'
|
3
3
|
require 'tempfile'
|
4
4
|
|
5
|
-
class Indocker::ConfigurationDeployer
|
5
|
+
class Indocker::Launchers::ConfigurationDeployer
|
6
6
|
REMOTE_OPERATION_TIMEOUT = 60
|
7
7
|
|
8
8
|
def initialize(logger:, global_logger:)
|
@@ -14,13 +14,11 @@ class Indocker::ConfigurationDeployer
|
|
14
14
|
@progress = Indocker::DeploymentProgress.new(
|
15
15
|
Indocker.logger.level == Logger::DEBUG ? nil : Logger.new(STDOUT)
|
16
16
|
)
|
17
|
+
@compiled_images = Hash.new(false)
|
17
18
|
end
|
18
19
|
|
19
20
|
# Launch deployment & measure the benchmark
|
20
21
|
def run(configuration:, deployment_policy:)
|
21
|
-
build_context_pool = nil
|
22
|
-
deployer = nil
|
23
|
-
|
24
22
|
time = Benchmark.realtime do
|
25
23
|
if deployment_policy.force_restart
|
26
24
|
@logger.warn("WARNING. All containers will be forced to restart.")
|
@@ -46,12 +44,11 @@ class Indocker::ConfigurationDeployer
|
|
46
44
|
containers = find_containers_to_deploy(configuration, deployment_policy)
|
47
45
|
|
48
46
|
clonner = Indocker::Repositories::Clonner.new(configuration, @logger)
|
49
|
-
|
47
|
+
build_server_pool = Indocker::ServerPools::BuildServerPool.new(configuration: configuration, logger: @logger)
|
50
48
|
deployer = Indocker::ContainerDeployer.new(configuration: configuration, logger: @logger)
|
51
49
|
|
52
50
|
@global_logger.info("Establishing ssh sessions to all servers...")
|
53
|
-
|
54
|
-
deployer.create_sessions!
|
51
|
+
build_server_pool.create_sessions!
|
55
52
|
|
56
53
|
build_servers = configuration
|
57
54
|
.build_servers
|
@@ -95,7 +92,7 @@ class Indocker::ConfigurationDeployer
|
|
95
92
|
recursively_deploy_container(
|
96
93
|
configuration,
|
97
94
|
deployer,
|
98
|
-
|
95
|
+
build_server_pool,
|
99
96
|
container,
|
100
97
|
containers,
|
101
98
|
deployment_policy.skip_build,
|
@@ -109,7 +106,7 @@ class Indocker::ConfigurationDeployer
|
|
109
106
|
.list
|
110
107
|
.each { |t| t.join if t != Thread.current }
|
111
108
|
ensure
|
112
|
-
|
109
|
+
build_server_pool.close_sessions if build_server_pool
|
113
110
|
deployer.close_sessions if deployer
|
114
111
|
end
|
115
112
|
|
@@ -272,12 +269,12 @@ class Indocker::ConfigurationDeployer
|
|
272
269
|
result.uniq
|
273
270
|
end
|
274
271
|
|
275
|
-
def compile_image(configuration, image,
|
276
|
-
return if
|
272
|
+
def compile_image(configuration, image, build_server)
|
273
|
+
return if @compiled_images[image]
|
277
274
|
|
278
275
|
image.dependent_images.each do |dependent_image|
|
279
|
-
next if
|
280
|
-
compile_image(configuration, dependent_image,
|
276
|
+
next if @compiled_images[image]
|
277
|
+
compile_image(configuration, dependent_image, build_server)
|
281
278
|
end
|
282
279
|
|
283
280
|
compiler = Indocker::Images::ImageCompiler.new
|
@@ -287,32 +284,30 @@ class Indocker::ConfigurationDeployer
|
|
287
284
|
result = nil
|
288
285
|
|
289
286
|
time = Benchmark.realtime do
|
290
|
-
result =
|
291
|
-
.
|
292
|
-
|
293
|
-
|
287
|
+
result = build_server
|
288
|
+
.compile_image_remotely(
|
289
|
+
configuration_name: Indocker.configuration_name,
|
290
|
+
image_name: image.name
|
294
291
|
)
|
295
292
|
end
|
296
293
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
exit 1 if result.exit_code != 0
|
294
|
+
if result.exit_code != 0
|
295
|
+
exit 1
|
296
|
+
end
|
302
297
|
|
303
298
|
@logger.info("Image compilation completed #{image.name.to_s.green}. Time taken: #{time}")
|
304
299
|
|
305
|
-
|
300
|
+
@compiled_images[image] = true
|
306
301
|
end
|
307
302
|
|
308
|
-
def recursively_deploy_container(configuration, deployer,
|
303
|
+
def recursively_deploy_container(configuration, deployer, build_server_pool, container,
|
309
304
|
containers, skip_build, skip_deploy, force_restart, skip_force_restart)
|
310
305
|
|
311
306
|
container.dependent_containers.each do |container|
|
312
307
|
recursively_deploy_container(
|
313
308
|
configuration,
|
314
309
|
deployer,
|
315
|
-
|
310
|
+
build_server_pool,
|
316
311
|
container,
|
317
312
|
containers,
|
318
313
|
skip_build,
|
@@ -327,20 +322,24 @@ class Indocker::ConfigurationDeployer
|
|
327
322
|
@progress.start_building_container(container)
|
328
323
|
|
329
324
|
if !skip_build
|
330
|
-
|
325
|
+
build_server = build_server_pool.get
|
331
326
|
|
332
|
-
|
333
|
-
compile_image(configuration, container.image,
|
334
|
-
|
327
|
+
build_server.set_busy(true)
|
328
|
+
compile_image(configuration, container.image, build_server)
|
329
|
+
build_server.set_busy(false)
|
335
330
|
end
|
336
331
|
|
337
332
|
@progress.finish_building_container(container)
|
338
333
|
|
339
334
|
if !skip_deploy
|
340
|
-
deployer
|
335
|
+
deploy_container(deployer, container, force_restart, skip_force_restart)
|
341
336
|
end
|
342
337
|
end
|
343
338
|
|
339
|
+
def deploy_container(deployer, container, force_restart, skip_force_restart)
|
340
|
+
deployer.deploy(container, force_restart, skip_force_restart, @progress)
|
341
|
+
end
|
342
|
+
|
344
343
|
class RemoteOperation
|
345
344
|
attr_reader :thread, :server, :operation, :message
|
346
345
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class Indocker::ContainerRunner
|
1
|
+
class Indocker::Launchers::ContainerRunner
|
2
2
|
def initialize(logger)
|
3
3
|
@logger = logger
|
4
4
|
end
|
@@ -13,8 +13,7 @@ class Indocker::ContainerRunner
|
|
13
13
|
|
14
14
|
deploy_context = Indocker::DeployContext.new(
|
15
15
|
logger: @logger,
|
16
|
-
configuration: configuration
|
17
|
-
server: nil
|
16
|
+
configuration: configuration
|
18
17
|
)
|
19
18
|
|
20
19
|
container = configuration.containers.detect { |c| c.name == container_name }
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class Indocker::ImagesCompiler
|
1
|
+
class Indocker::Launchers::ImagesCompiler
|
2
2
|
def initialize(logger)
|
3
3
|
@logger = logger
|
4
4
|
end
|
@@ -8,8 +8,8 @@ class Indocker::ImagesCompiler
|
|
8
8
|
|
9
9
|
build_context = Indocker::BuildContext.new(
|
10
10
|
configuration: configuration,
|
11
|
-
|
12
|
-
|
11
|
+
logger: @logger,
|
12
|
+
global_logger: Indocker.global_logger
|
13
13
|
)
|
14
14
|
|
15
15
|
image_compiler = Indocker::Images::ImageCompiler.new
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
class Indocker::ServerPools::BuildServerConnection < Indocker::ServerPools::ServerConnection
|
4
|
+
def compile_image_remotely(configuration_name:, image_name:)
|
5
|
+
result = exec!(
|
6
|
+
"cd #{Indocker::IndockerHelper.indocker_dir} && ./bin/remote/compile -C #{configuration_name} -i #{image_name} -s #{@logger.debug? ? '-d' : ''}"
|
7
|
+
)
|
8
|
+
|
9
|
+
Indocker::SshResultLogger
|
10
|
+
.new(@logger)
|
11
|
+
.log(result, "#{image_name.to_s.green} image compilation failed")
|
12
|
+
|
13
|
+
result
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Indocker::ServerPools::BuildServerPool
|
2
|
+
def initialize(configuration:, logger:)
|
3
|
+
@logger = logger
|
4
|
+
@configuration = configuration
|
5
|
+
|
6
|
+
@connections = configuration.build_servers.map do |build_server|
|
7
|
+
Indocker::ServerPools::BuildServerConnection.new(
|
8
|
+
logger: @logger,
|
9
|
+
configuration: configuration,
|
10
|
+
server: build_server,
|
11
|
+
)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_sessions!
|
16
|
+
@connections.each(&:create_session!)
|
17
|
+
end
|
18
|
+
|
19
|
+
def get
|
20
|
+
context = nil
|
21
|
+
|
22
|
+
loop do
|
23
|
+
context = @connections.detect {|c| !c.busy?}
|
24
|
+
sleep(0.1)
|
25
|
+
break if context
|
26
|
+
end
|
27
|
+
|
28
|
+
context
|
29
|
+
end
|
30
|
+
|
31
|
+
def each(&proc)
|
32
|
+
@connections.each(&proc)
|
33
|
+
end
|
34
|
+
|
35
|
+
def close_sessions
|
36
|
+
@connections.each(&:close_session)
|
37
|
+
rescue => e
|
38
|
+
@logger.error("error during session close: #{e.inspect}")
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Indocker::ServerPools::DeployServerConnection < Indocker::ServerPools::ServerConnection
|
2
|
+
def run_container_remotely(configuration_name:, container_name:, force_restart:)
|
3
|
+
command_output = @logger.debug? ? "" : " > /dev/null"
|
4
|
+
debug_options = @logger.debug? ? "-d" : ""
|
5
|
+
force_restart_options = force_restart ? "-f" : ""
|
6
|
+
|
7
|
+
result = exec!(
|
8
|
+
"cd #{Indocker::IndockerHelper.indocker_dir} && ./bin/remote/run -C #{configuration_name} -c #{container_name} #{debug_options} #{command_output} #{force_restart_options}"
|
9
|
+
)
|
10
|
+
|
11
|
+
Indocker::SshResultLogger
|
12
|
+
.new(@logger)
|
13
|
+
.log(result, "#{container_name.to_s.green} deployment for server #{server.name} failed")
|
14
|
+
|
15
|
+
result
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class Indocker::ServerPools::DeployServerPool
|
2
|
+
def initialize(configuration:, logger:)
|
3
|
+
@logger = logger
|
4
|
+
@configuration = configuration
|
5
|
+
@connections = []
|
6
|
+
@semaphore = Mutex.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_connection!(server)
|
10
|
+
@semaphore.synchronize do
|
11
|
+
create_connection_unsafe!(server)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def each(&proc)
|
16
|
+
@connections.each(&proc)
|
17
|
+
end
|
18
|
+
|
19
|
+
def close_sessions
|
20
|
+
@connections.each(&:close_session)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def create_connection_unsafe!(server)
|
25
|
+
connection = @connections.detect do |connection|
|
26
|
+
connection.server.host == server.host &&
|
27
|
+
connection.server.port == server.port &&
|
28
|
+
connection.server.user == server.user
|
29
|
+
end
|
30
|
+
if connection.nil?
|
31
|
+
connection = Indocker::ServerPools::DeployServerConnection.new(
|
32
|
+
logger: @logger,
|
33
|
+
configuration: @configuration,
|
34
|
+
server: server,
|
35
|
+
)
|
36
|
+
connection.create_session!
|
37
|
+
@connections.push(connection)
|
38
|
+
end
|
39
|
+
connection
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class Indocker::ServerPools::ServerConnection
|
2
|
+
attr_reader :server, :session
|
3
|
+
|
4
|
+
def initialize(logger:, configuration:, server:)
|
5
|
+
@logger = logger
|
6
|
+
@configuration = configuration
|
7
|
+
@server = server
|
8
|
+
end
|
9
|
+
|
10
|
+
def create_session!
|
11
|
+
return unless @server
|
12
|
+
|
13
|
+
@session = Indocker::SshSession.new(
|
14
|
+
host: @server.host,
|
15
|
+
user: @server.user,
|
16
|
+
port: @server.port,
|
17
|
+
logger: @logger
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
def exec!(command)
|
22
|
+
@session.exec!(command)
|
23
|
+
end
|
24
|
+
|
25
|
+
def close_session
|
26
|
+
@session.close if @session
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_busy(flag)
|
30
|
+
@busy = !!flag
|
31
|
+
end
|
32
|
+
|
33
|
+
def busy?
|
34
|
+
!!@busy
|
35
|
+
end
|
36
|
+
end
|
data/lib/indocker/ssh_session.rb
CHANGED
@@ -38,10 +38,26 @@ class Indocker::SshSession
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def exec!(command)
|
41
|
-
if
|
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
|
-
|
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
|