indocker 0.1.9 → 0.1.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -0
  3. data/Gemfile +0 -1
  4. data/Gemfile.lock +10 -4
  5. data/example/indocker/bounded_contexts/shared/{container_failing_build → bad_container_build}/Dockerfile +0 -1
  6. data/example/indocker/bounded_contexts/shared/bad_container_build/container.rb +6 -0
  7. data/example/indocker/bounded_contexts/shared/bad_container_build/image.rb +3 -0
  8. data/example/indocker/bounded_contexts/shared/bad_container_start/Dockerfile +8 -0
  9. data/example/indocker/bounded_contexts/shared/bad_container_start/build_context/bin/run +3 -0
  10. data/example/indocker/bounded_contexts/shared/bad_container_start/container.rb +6 -0
  11. data/example/indocker/bounded_contexts/shared/bad_container_start/image.rb +3 -0
  12. data/example/indocker/bounded_contexts/shared/daemon_container/Dockerfile +4 -0
  13. data/example/indocker/bounded_contexts/shared/daemon_container/container.rb +6 -0
  14. data/example/indocker/bounded_contexts/shared/daemon_container/image.rb +3 -0
  15. data/example/indocker/bounded_contexts/shared/good_container/Dockerfile +4 -0
  16. data/example/indocker/bounded_contexts/shared/good_container/container.rb +6 -0
  17. data/example/indocker/bounded_contexts/shared/good_container/image.rb +3 -0
  18. data/example/indocker/bounded_contexts/shared/ruby/container.rb +2 -1
  19. data/example/indocker/configurations/external.rb +13 -2
  20. data/example/indocker/infrastructure/artifacts.rb +10 -0
  21. data/example/indocker/setup.rb +1 -0
  22. data/indocker.gemspec +2 -1
  23. data/lib/indocker.rb +24 -12
  24. data/lib/indocker/build_context.rb +6 -41
  25. data/lib/indocker/container_deployer.rb +12 -23
  26. data/lib/indocker/crontab_redeploy_rules_builder.rb +2 -1
  27. data/lib/indocker/deploy_context.rb +4 -32
  28. data/lib/indocker/docker_run_args.rb +2 -2
  29. data/lib/indocker/images/image_compiler.rb +0 -1
  30. data/lib/indocker/{configuration_deployer.rb → launchers/configuration_deployer.rb} +29 -30
  31. data/lib/indocker/{container_runner.rb → launchers/container_runner.rb} +2 -3
  32. data/lib/indocker/{images_compiler.rb → launchers/images_compiler.rb} +3 -3
  33. data/lib/indocker/{network.rb → networks/network.rb} +1 -1
  34. data/lib/indocker/{network_helper.rb → networks/network_helper.rb} +1 -1
  35. data/lib/indocker/server_pools/build_server_connection.rb +15 -0
  36. data/lib/indocker/server_pools/build_server_pool.rb +40 -0
  37. data/lib/indocker/server_pools/deploy_server_connection.rb +17 -0
  38. data/lib/indocker/server_pools/deploy_server_pool.rb +41 -0
  39. data/lib/indocker/server_pools/server_connection.rb +36 -0
  40. data/lib/indocker/ssh_session.rb +18 -9
  41. data/lib/indocker/version.rb +1 -1
  42. data/lib/indocker/{volume_helper.rb → volumes/volume_helper.rb} +1 -1
  43. metadata +44 -17
  44. data/example/indocker/bounded_contexts/shared/container_failing_build/container.rb +0 -5
  45. data/example/indocker/bounded_contexts/shared/container_failing_build/image.rb +0 -3
  46. data/example/spec/indocker_spec.rb +0 -31
  47. data/example/spec/spec_helper.rb +0 -39
  48. data/lib/indocker/build_context_pool.rb +0 -42
  49. 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 :server, :session
5
+ attr_reader :configuration, :logger
6
6
 
7
- def initialize(logger:, configuration:, server:)
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
 
@@ -61,7 +61,6 @@ class Indocker::Images::ImageCompiler
61
61
  end
62
62
 
63
63
  build_context.build_image(image, compile_dir)
64
- build_context.set_compiled(image)
65
64
 
66
65
  @compiled_images[image] = true
67
66
  end
@@ -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
- build_context_pool = Indocker::BuildContextPool.new(configuration: configuration, logger: @logger, global_logger: @global_logger)
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
- build_context_pool.create_sessions!
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
- build_context_pool,
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
- build_context_pool.close_sessions if build_context_pool
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, build_context)
276
- return if build_context.image_compiled?(image)
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 build_context.image_compiled?(dependent_image)
280
- compile_image(configuration, dependent_image, build_context)
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 = build_context
291
- .session
292
- .exec!(
293
- "cd #{Indocker::IndockerHelper.indocker_dir} && ./bin/remote/compile -C #{Indocker.configuration_name} -i #{image.name} -s #{@logger.debug? ? '-d' : ''}"
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
- Indocker::SshResultLogger
298
- .new(@logger)
299
- .log(result, "#{image.name.to_s.green} image compilation failed")
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
- build_context.set_compiled(image)
300
+ @compiled_images[image] = true
306
301
  end
307
302
 
308
- def recursively_deploy_container(configuration, deployer, build_context_pool, container,
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
- build_context_pool,
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
- build_context = build_context_pool.get
325
+ build_server = build_server_pool.get
331
326
 
332
- build_context.set_busy(true)
333
- compile_image(configuration, container.image, build_context)
334
- build_context.set_busy(false)
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.deploy(container, force_restart, skip_force_restart, @progress)
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
- build_server: nil,
12
- logger: Indocker.logger
11
+ logger: @logger,
12
+ global_logger: Indocker.global_logger
13
13
  )
14
14
 
15
15
  image_compiler = Indocker::Images::ImageCompiler.new
@@ -1,4 +1,4 @@
1
- class Indocker::Network
1
+ class Indocker::Networks::Network
2
2
  attr_reader :name, :containers
3
3
 
4
4
  def initialize(name)
@@ -1,4 +1,4 @@
1
- class Indocker::NetworkHelper
1
+ class Indocker::Networks::NetworkHelper
2
2
  class << self
3
3
  def name(configuration_name, network)
4
4
  "#{configuration_name}_#{network.name}"
@@ -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
@@ -38,10 +38,26 @@ class Indocker::SshSession
38
38
  end
39
39
 
40
40
  def exec!(command)
41
- if !@ssh
41
+ if local?
42
+ exec_locally!(command)
43
+ else
44
+ exec_remotely!(command)
45
+ end
46
+ end
47
+
48
+ def close
49
+ if @ssh
50
+ @ssh.close
51
+ end
52
+ end
53
+
54
+ private
55
+ def exec_locally!(command)
42
56
  res = Indocker::Shell.command_with_result(command, @logger, skip_logging: false)
43
57
  ExecResult.new(res.stdout, '', res.exit_status, nil)
44
- else
58
+ end
59
+
60
+ def exec_remotely!(command)
45
61
  if Indocker.export_command
46
62
  command = "#{Indocker.export_command} && #{command}"
47
63
  end
@@ -82,11 +98,4 @@ class Indocker::SshSession
82
98
 
83
99
  ExecResult.new(stdout_data, stderr_data, exit_code, exit_signal)
84
100
  end
85
- end
86
-
87
- def close
88
- if @ssh
89
- @ssh.close
90
- end
91
- end
92
101
  end