moby-derp 0.5.0 → 0.6.0
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/example.yml +27 -0
- data/lib/moby_derp/container.rb +29 -1
- data/lib/moby_derp/container_config.rb +51 -3
- data/lib/moby_derp/error.rb +4 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 513a47c0b56a264731bf12050cbc651c7799c4ec60955c06e8cff46377328825
|
4
|
+
data.tar.gz: 01d2f26f2fa6300cdddf599b9f544616d1781c4a53879ec009bec1d4dd340b9d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 307556e56b26e97437df00b9db1277f254554ba88af5a22d9b786de2daba8a30d91f5c932c3b28f4cebb972175958c7c1be81d3cd8ad718a23638d8f696aaa12
|
7
|
+
data.tar.gz: eb0c7f7f7514dbb93911cc65037a129aadfc1888454529071f2811e606dd3291dc57e5f2ced377df3896bbaccbac22c163bd5fad4e90cc0435304bb32b65ef6a
|
data/example.yml
CHANGED
@@ -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
|
data/lib/moby_derp/container.rb
CHANGED
@@ -43,7 +43,35 @@ module MobyDerp
|
|
43
43
|
end
|
44
44
|
|
45
45
|
begin
|
46
|
-
Docker::Container.create(hash_labelled(container_creation_parameters))
|
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
|
data/lib/moby_derp/error.rb
CHANGED
@@ -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.
|
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-
|
11
|
+
date: 2020-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: docker-api
|