moby-derp 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 99faf7a4a2ccef6a30df32e08d424bf89c5693278100484a75e21276136e6a3a
4
- data.tar.gz: 379c96e91a43e3b19db58d0e61d1324749969f58a2946a72f687429cda959f34
3
+ metadata.gz: 513a47c0b56a264731bf12050cbc651c7799c4ec60955c06e8cff46377328825
4
+ data.tar.gz: 01d2f26f2fa6300cdddf599b9f544616d1781c4a53879ec009bec1d4dd340b9d
5
5
  SHA512:
6
- metadata.gz: 6d7b1071d6a38f8aa880ad7287c7355460a32dc4a66250e13bcec612d1f11ee91530d2cfedbba0bb4e8bdf54f5784fbaac00f807a46a967a35ddf45193feb6a6
7
- data.tar.gz: ef1b7425e29551844fe383159a19010cc611ffc8dc07566f4c7e30afa4d3d02882692a3beaed35d6490263d51e093decd662e59b9e0169f177f2c221eb9079c4
6
+ metadata.gz: 307556e56b26e97437df00b9db1277f254554ba88af5a22d9b786de2daba8a30d91f5c932c3b28f4cebb972175958c7c1be81d3cd8ad718a23638d8f696aaa12
7
+ data.tar.gz: eb0c7f7f7514dbb93911cc65037a129aadfc1888454529071f2811e606dd3291dc57e5f2ced377df3896bbaccbac22c163bd5fad4e90cc0435304bb32b65ef6a
@@ -213,6 +213,33 @@ containers:
213
213
  ulimit-rttime: 15:16
214
214
  ulimit-stack: 17:18
215
215
 
216
+ # If you're a bit suss as to whether or not one of your containers will
217
+ # successfully start up, you can use the following section to define a
218
+ # start-time health checking regime.
219
+ #
220
+ # How it works is that the defined command is run in the container (using
221
+ # `exec`), and if-and-when that command returns a `0` exit status, the
222
+ # container is considered to be healthy and we're done. If the command
223
+ # returns a non-zero exit status, we wait for `interval` seconds and then
224
+ # retry. If the command executes `attempts` times without receiving a `0`
225
+ # exit status, the container is considered "failed", and no further
226
+ # containers in the pod will be processed, and the `moby-derp` execution
227
+ # will itself exit with a non-zero status.
228
+ startup_health_check:
229
+ # The command to run inside the container via `exec`. You can specify
230
+ # this as a string, or as an array of strings if you prefer to avoid
231
+ # shell quoting hell.
232
+ command: '/usr/local/bin/r-u-ok'
233
+
234
+ # How many seconds to wait between invocations of the command, when
235
+ # it fails. Can be any non-negative number. Defaults to 3.
236
+ interval: 3
237
+
238
+ # How many times to attempt to execute the health-check command before
239
+ # declaring the container hopelessly busticated, and aborting the
240
+ # `moby-derp` run. Must be a positive integer. Defaults to 10.
241
+ attempts: 10
242
+
216
243
  # SECTION 2: POD-LEVEL CONFIGURATION
217
244
  #
218
245
  # The remainder of the configuration items in this file correspond to settings
@@ -43,7 +43,35 @@ module MobyDerp
43
43
  end
44
44
 
45
45
  begin
46
- Docker::Container.create(hash_labelled(container_creation_parameters)).start!.id
46
+ c = Docker::Container.create(hash_labelled(container_creation_parameters))
47
+ c.start!.object_id
48
+
49
+ if @config.startup_health_check
50
+ attempts = @config.startup_health_check[:attempts]
51
+
52
+ while attempts > 0
53
+ stdout, stderr, exitstatus = c.exec(@config.startup_health_check[:command])
54
+ if exitstatus > 0
55
+ stdout_lines = stdout.empty? ? [] : ["stdout:"] + stdout.join("\n").split("\n").map { |l| " #{l}" }
56
+ stderr_lines = stderr.empty? ? [] : ["stderr:"] + stderr.join("\n").split("\n").map { |l| " #{l}" }
57
+ output_lines = stdout_lines + stderr_lines
58
+ @logger.warn(logloc) { "Startup health check failed on #{container_name} with status #{exitstatus}." + (output_lines.empty? ? "" : ([" Output:"] + output_lines.join("\n "))) }
59
+
60
+ attempts -= 1
61
+ sleep @config.startup_health_check[:interval]
62
+ else
63
+ @logger.info(logloc) { "Startup health check passed." }
64
+ break
65
+ end
66
+ end
67
+
68
+ if attempts == 0
69
+ raise MobyDerp::StartupHealthCheckError,
70
+ "Container #{container_name} has failed the startup health check command #{@config.startup_health_check[:attempts]} times. Aborting."
71
+ end
72
+ end
73
+
74
+ c.id
47
75
  rescue Docker::Error::ClientError => ex
48
76
  raise MobyDerp::ContainerError,
49
77
  "moby daemon returned error: #{ex.message}"
@@ -8,7 +8,8 @@ require "shellwords"
8
8
  module MobyDerp
9
9
  class ContainerConfig
10
10
  attr_reader :name, :image, :update_image, :command, :environment, :mounts,
11
- :labels, :readonly, :stop_signal, :stop_timeout, :user, :restart, :limits
11
+ :labels, :readonly, :stop_signal, :stop_timeout, :user, :restart, :limits,
12
+ :startup_health_check
12
13
 
13
14
  def initialize(system_config:,
14
15
  pod_config:,
@@ -24,13 +25,14 @@ module MobyDerp
24
25
  stop_timeout: 10,
25
26
  user: nil,
26
27
  restart: "no",
27
- limits: {}
28
+ limits: {},
29
+ startup_health_check: nil
28
30
  )
29
31
  @system_config, @pod_config, @name, @image = system_config, pod_config, "#{pod_config.name}.#{container_name}", image
30
32
 
31
33
  @update_image, @command, @environment, @mounts, @labels = update_image, command, environment, mounts, labels
32
34
  @readonly, @stop_signal, @stop_timeout, @user, @restart = readonly, stop_signal, stop_timeout, user, restart
33
- @limits = limits
35
+ @limits, @startup_health_check = limits, startup_health_check
34
36
 
35
37
  validate_image
36
38
  validate_update_image
@@ -44,6 +46,7 @@ module MobyDerp
44
46
  validate_user
45
47
  validate_restart
46
48
  validate_limits
49
+ validate_startup_health_check
47
50
  end
48
51
 
49
52
  private
@@ -331,6 +334,51 @@ module MobyDerp
331
334
  end
332
335
  end
333
336
 
337
+ def validate_startup_health_check
338
+ if @startup_health_check.nil?
339
+ # This is fine
340
+ return
341
+ end
342
+
343
+ unless @startup_health_check.is_a?(Hash)
344
+ raise ConfigurationError,
345
+ "startup_health_check must be a hash"
346
+ end
347
+
348
+ case @startup_health_check[:command]
349
+ when String
350
+ @startup_health_check[:command] = Shellwords.split(@startup_health_check[:command])
351
+ when Array
352
+ unless @startup_health_check[:command].all? { |c| String === c }
353
+ raise ConfigurationError, "all elements of the health check command array must be strings"
354
+ end
355
+ when NilClass
356
+ raise ConfigurationError, "health check command must be specified"
357
+ else
358
+ raise ConfigurationError,
359
+ "health check command must be string or array of strings"
360
+ end
361
+
362
+ @startup_health_check[:interval] ||= 3
363
+ @startup_health_check[:attempts] ||= 10
364
+
365
+ unless Numeric === @startup_health_check[:interval]
366
+ raise ConfigurationError, "startup health check interval must be a number"
367
+ end
368
+
369
+ if @startup_health_check[:interval] < 0
370
+ raise ConfigurationError, "startup health check interval cannot be negative"
371
+ end
372
+
373
+ unless Integer === @startup_health_check[:attempts]
374
+ raise ConfigurationError, "startup health check attempt count must be an integer"
375
+ end
376
+
377
+ if @startup_health_check[:attempts] < 1
378
+ raise ConfigurationError, "startup health check attempt count must be a positive integer"
379
+ end
380
+ end
381
+
334
382
  def validate_boolean(name)
335
383
  v = instance_variable_get(:"@#{name}")
336
384
  unless v == true || v == false
@@ -9,6 +9,10 @@ module MobyDerp
9
9
  # Indicates there was a problem manipulating a live container
10
10
  class ContainerError < Error; end
11
11
 
12
+ # Raised when the startup health check has failed spectacularly for
13
+ # a container
14
+ class StartupHealthCheckError < Error; end
15
+
12
16
  # Only appears when an inviolable assertion is invalid, and indicates
13
17
  # there is a bug in the code
14
18
  class BugError < Error; end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moby-derp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Palmer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-10 00:00:00.000000000 Z
11
+ date: 2020-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: docker-api