moby-derp 0.3.3 → 0.7.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: 443db141ccca9522f7fe188a5fb5b0ed972197eb4de18e899ad275adaf16689c
4
- data.tar.gz: 75c10f4b97000efccd2ba4f0bda78b8a5fa44a77c6e1e37262a8744324242b88
3
+ metadata.gz: 0c2890cb17a2175bed1a51fce4f28ac8e898555b62c28f626ff7d87bd26b21ec
4
+ data.tar.gz: c49fe1673ac2380e964c7b37b5605c18a52b6f0ec095e6ffba8c345afcf179c6
5
5
  SHA512:
6
- metadata.gz: f75ffe9184bdcc0949ee6030b04927e7821c4bfa4a9a7d3ede99947f24f05580d58e28edd9efc253fa420c733a1d64e8a3cc85bc3df900e6479d9de35a8c39f6
7
- data.tar.gz: dcc3c3a0ac2ed25d321b15118a876f3b40288ba028736324ee61b5783615da74d941532c000fd01795ecdf316e8c56a95b5a18332dd9a9e1c180224b87eeba4a
6
+ metadata.gz: c2d2cae1b30c7c75a021adfb5c40b5cf1a658828383236e0852fec61c79e5ddf4ff50bdecff8fa1319b3afc35624c03d79410a2505385ffc9ebaefb4121f25ea
7
+ data.tar.gz: f51fce566d449b97f8a938722f58484668d1e3b220e95f53aee4788ef9f72d2f2f54073cbb55770546e92304e42d36006e1ce67b524da36f81cea6cde9482aa6
data/README.md CHANGED
@@ -134,7 +134,7 @@ wrapper script, like this:
134
134
 
135
135
  set -e
136
136
 
137
- MOBY_DERP_SYSTEM_CONFIG_FILE=/opt/srv/etc/moby-derp/moby-derp.yaml
137
+ export MOBY_DERP_SYSTEM_CONFIG_FILE=/opt/srv/etc/moby-derp/moby-derp.yaml
138
138
 
139
139
  exec /usr/local/bin/moby-derp "$@"
140
140
 
@@ -185,7 +185,7 @@ to `moby-derp`. This means that, yes, different users need to use different
185
185
  filenames. The benefit of this is that the `sudo` configuration becomes a lot
186
186
  easier to audit -- the pod name is right there.
187
187
 
188
- This means that no matter a user does, they cannot have any effect on any
188
+ This means that no matter what a user does, they cannot have any effect on any
189
189
  container which is not named for the pod they're manipulating. There are also
190
190
  safety valves around `moby-derp`-managed containers being labelled as such, so
191
191
  that in the event that someone does inadvertently name a container in such a
@@ -220,7 +220,7 @@ still publish to ephemeral ports (using the `:containerPort` syntax, or
220
220
  `publish_all: true`) if they wish.
221
221
 
222
222
  If a pod *does* need to bind to a specific host port, then that pod/port pair
223
- should be whitelisted in the system configuration file.
223
+ should be whitelisted in the [system configuration file](#system-configuration).
224
224
 
225
225
 
226
226
  # Contributing
@@ -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
@@ -1,7 +1,7 @@
1
1
  require_relative "./error"
2
2
  require_relative "./logging_helpers"
3
3
 
4
- require "safe_yaml"
4
+ require "yaml"
5
5
 
6
6
  module MobyDerp
7
7
  class ConfigFile
@@ -12,7 +12,7 @@ module MobyDerp
12
12
  def initialize(filename)
13
13
  begin
14
14
  @logger.debug(logloc) { "Reading configuration file #{filename}" }
15
- @config = SafeYAML.load(File.read(filename))
15
+ @config = YAML.safe_load(File.read(filename))
16
16
  rescue Errno::ENOENT
17
17
  raise ConfigurationError,
18
18
  "file does not exist"
@@ -5,6 +5,8 @@ require "docker-api"
5
5
  require "ipaddr"
6
6
  require "json/canonicalization"
7
7
 
8
+ require_relative "./freedom_patches/docker/credential"
9
+
8
10
  module MobyDerp
9
11
  class Container
10
12
  include LoggingHelpers
@@ -43,7 +45,35 @@ module MobyDerp
43
45
  end
44
46
 
45
47
  begin
46
- Docker::Container.create(hash_labelled(container_creation_parameters)).start!.id
48
+ c = Docker::Container.create(hash_labelled(container_creation_parameters))
49
+ c.start!.object_id
50
+
51
+ if @config.startup_health_check
52
+ attempts = @config.startup_health_check[:attempts]
53
+
54
+ while attempts > 0
55
+ stdout, stderr, exitstatus = c.exec(@config.startup_health_check[:command])
56
+ if exitstatus > 0
57
+ stdout_lines = stdout.empty? ? [] : ["stdout:"] + stdout.join("\n").split("\n").map { |l| " #{l}" }
58
+ stderr_lines = stderr.empty? ? [] : ["stderr:"] + stderr.join("\n").split("\n").map { |l| " #{l}" }
59
+ output_lines = stdout_lines + stderr_lines
60
+ @logger.warn(logloc) { "Startup health check failed on #{container_name} with status #{exitstatus}." + (output_lines.empty? ? "" : ([" Output:"] + output_lines.join("\n "))) }
61
+
62
+ attempts -= 1
63
+ sleep @config.startup_health_check[:interval]
64
+ else
65
+ @logger.info(logloc) { "Startup health check passed." }
66
+ break
67
+ end
68
+ end
69
+
70
+ if attempts == 0
71
+ raise MobyDerp::StartupHealthCheckError,
72
+ "Container #{container_name} has failed the startup health check command #{@config.startup_health_check[:attempts]} times. Aborting."
73
+ end
74
+ end
75
+
76
+ c.id
47
77
  rescue Docker::Error::ClientError => ex
48
78
  raise MobyDerp::ContainerError,
49
79
  "moby daemon returned error: #{ex.message}"
@@ -71,6 +101,7 @@ module MobyDerp
71
101
  }
72
102
  }
73
103
  end
104
+ params["ExposedPorts"] = Hash[@pod.expose.map { |ex| [ex, {}] }]
74
105
  else
75
106
  params["HostConfig"] = {
76
107
  "NetworkMode" => "container:#{@pod.root_container_id}",
@@ -126,7 +157,9 @@ module MobyDerp
126
157
  params["Labels"] = @pod.common_labels.merge(@config.labels)
127
158
  params["Labels"]["org.hezmatt.moby-derp.pod-name"] = @pod.name
128
159
 
129
- unless @root_container
160
+ if @root_container
161
+ params["Labels"] = @pod.root_labels.merge(params["Labels"])
162
+ else
130
163
  params["Labels"]["org.hezmatt.moby-derp.root-container-id"] = @pod.root_container_id
131
164
  end
132
165
  end
@@ -1,13 +1,15 @@
1
- require_relative "../freedom_patches/docker/image"
1
+ require_relative "./freedom_patches/docker/image"
2
2
  require_relative "./error"
3
3
  require_relative "./mount"
4
4
 
5
5
  require "docker-api"
6
+ require "shellwords"
6
7
 
7
8
  module MobyDerp
8
9
  class ContainerConfig
9
10
  attr_reader :name, :image, :update_image, :command, :environment, :mounts,
10
- :labels, :readonly, :stop_signal, :stop_timeout, :user, :restart, :limits
11
+ :labels, :readonly, :stop_signal, :stop_timeout, :user, :restart, :limits,
12
+ :startup_health_check
11
13
 
12
14
  def initialize(system_config:,
13
15
  pod_config:,
@@ -23,13 +25,14 @@ module MobyDerp
23
25
  stop_timeout: 10,
24
26
  user: nil,
25
27
  restart: "no",
26
- limits: {}
28
+ limits: {},
29
+ startup_health_check: nil
27
30
  )
28
31
  @system_config, @pod_config, @name, @image = system_config, pod_config, "#{pod_config.name}.#{container_name}", image
29
32
 
30
33
  @update_image, @command, @environment, @mounts, @labels = update_image, command, environment, mounts, labels
31
34
  @readonly, @stop_signal, @stop_timeout, @user, @restart = readonly, stop_signal, stop_timeout, user, restart
32
- @limits = limits
35
+ @limits, @startup_health_check = limits, startup_health_check
33
36
 
34
37
  validate_image
35
38
  validate_update_image
@@ -43,6 +46,7 @@ module MobyDerp
43
46
  validate_user
44
47
  validate_restart
45
48
  validate_limits
49
+ validate_startup_health_check
46
50
  end
47
51
 
48
52
  private
@@ -66,7 +70,10 @@ module MobyDerp
66
70
  def validate_command
67
71
  case @command
68
72
  when String
69
- true
73
+ # Despite the Docker Engine API spec saying you can pass a string,
74
+ # if you do it doesn't get parsed into arguments... so that's pretty
75
+ # fucking useless.
76
+ @command = Shellwords.split(@command)
70
77
  when Array
71
78
  unless @command.all? { |c| String === c }
72
79
  raise ConfigurationError, "all elements of the command array must be strings"
@@ -327,6 +334,51 @@ module MobyDerp
327
334
  end
328
335
  end
329
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
+
330
382
  def validate_boolean(name)
331
383
  v = instance_variable_get(:"@#{name}")
332
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
@@ -0,0 +1,91 @@
1
+ require "json"
2
+ require "open3"
3
+ require "pathname"
4
+ require "uri"
5
+
6
+ module Docker
7
+ module Credential
8
+ #:nocov:
9
+ def self.for(ref)
10
+ image_cred(ref)
11
+ end
12
+
13
+ private
14
+
15
+ def self.image_cred(ref)
16
+ cred_helper = hunt_for_image_domain_cred(ref, docker_config.fetch("credHelpers", {}))
17
+
18
+ if cred_helper
19
+ out, rv = Open3.capture2e("docker-credential-#{cred_helper}", "get", stdin_data: image_domain(ref))
20
+
21
+ if rv.exitstatus == 0
22
+ cred_data = JSON.parse(out)
23
+
24
+ { username: cred_data["Username"], password: cred_data["Secret"], serveraddress: image_domain(ref) }
25
+ else
26
+ raise RuntimeError, "Credential helper docker-credential-#{cred_helper} exited with #{rv.exitstatus}: #{out}"
27
+ end
28
+ else
29
+ cred = hunt_for_image_domain_cred(ref, docker_config.fetch("auths", {}))
30
+
31
+ if cred
32
+ user, pass = JSON.parse(cred.fetch("auth", "null"))&.unpack("m")&.first&.split(":", 2)
33
+
34
+ if user && pass
35
+ { username: user, password: pass, serveraddress: image_domain(ref) }
36
+ else
37
+ {}
38
+ end
39
+ else
40
+ {}
41
+ end
42
+ end
43
+ end
44
+
45
+ def self.hunt_for_image_domain_cred(ref, section)
46
+ section.find do |k, v|
47
+ if k =~ /:\/\//
48
+ # Doin' it URL style
49
+ URI(k).host == image_domain(ref)
50
+ else
51
+ k == image_domain(ref)
52
+ end
53
+ end&.last
54
+ end
55
+
56
+ def self.image_domain(ref)
57
+ if match_data = ref.match(Docker::Image::IMAGE_REFERENCE)
58
+ if match_data[1] =~ /[.:]/
59
+ match_data[1].gsub(/\/\z/, '')
60
+ else
61
+ "index.docker.io"
62
+ end
63
+ else
64
+ raise ArgumentError, "Could not parse image ref #{ref.inspect}"
65
+ end
66
+ end
67
+
68
+ def self.docker_config
69
+ if (f = Pathname.new(ENV.fetch("DOCKER_CONFIG", "~/.docker")).expand_path.join("config.json")).exist?
70
+ JSON.parse(f.read)
71
+ else
72
+ {}
73
+ end
74
+ end
75
+
76
+ module ImageClassMixin
77
+ def create(opts = {}, creds = nil, conn = Docker.connection, &block)
78
+ if creds.nil?
79
+ image = opts["fromImage"] || opts[:fromImage]
80
+
81
+ creds = Docker::Credential.for(image)
82
+ end
83
+
84
+ super(opts, creds, conn, &block)
85
+ end
86
+ end
87
+ #:nocov:
88
+ end
89
+ end
90
+
91
+ Docker::Image.singleton_class.prepend(Docker::Credential::ImageClassMixin)
@@ -18,6 +18,20 @@ module MobyDerp
18
18
 
19
19
  @logger.debug(logloc) { "Root container ID is #{@root_container_id}" }
20
20
 
21
+ desired_container_names = @config.containers.map(&:name)
22
+
23
+ Docker::Container.all(all: true).each do |c|
24
+ c_name = c.info["Names"].first.sub(/^\//, '')
25
+
26
+ if c.info["Labels"]["org.hezmatt.moby-derp.pod-name"] == name &&
27
+ !c.info["Labels"]["org.hezmatt.moby-derp.root-container-id"].nil? &&
28
+ !desired_container_names.include?(c_name.split(".", 2).last)
29
+ @logger.info(logloc) { "Removing stale container #{c_name}" }
30
+ c.stop
31
+ c.delete
32
+ end
33
+ end
34
+
21
35
  @config.containers.each do |cfg|
22
36
  @logger.info(logloc) { "Checking container #{cfg.name}" }
23
37
 
@@ -48,6 +62,10 @@ module MobyDerp
48
62
  @config.common_labels
49
63
  end
50
64
 
65
+ def root_labels
66
+ @config.root_labels
67
+ end
68
+
51
69
  def common_environment
52
70
  @config.common_environment
53
71
  end
@@ -68,6 +86,10 @@ module MobyDerp
68
86
  @config.hostname
69
87
  end
70
88
 
89
+ def expose
90
+ @config.expose
91
+ end
92
+
71
93
  private
72
94
 
73
95
  def root_container
@@ -3,13 +3,24 @@ require_relative "./container_config"
3
3
  require_relative "./logging_helpers"
4
4
  require_relative "./mount"
5
5
 
6
- require "safe_yaml"
7
6
  require "socket"
8
7
 
9
8
  module MobyDerp
10
9
  class PodConfig < ConfigFile
11
10
  include LoggingHelpers
12
11
 
12
+ VALID_CONFIG_KEYS = %w{
13
+ containers
14
+ hostname
15
+ common_environment
16
+ common_labels
17
+ root_labels
18
+ common_mounts
19
+ expose
20
+ publish
21
+ publish_all
22
+ }
23
+
13
24
  attr_reader :name,
14
25
  :containers,
15
26
  :hostname,
@@ -21,8 +32,8 @@ module MobyDerp
21
32
  :publish,
22
33
  :publish_all,
23
34
  :mount_root,
24
- :system_config,
25
- :logger
35
+ :system_config,
36
+ :logger
26
37
 
27
38
  def initialize(filename, system_config)
28
39
  @logger = system_config.logger
@@ -34,6 +45,10 @@ module MobyDerp
34
45
  @name = File.basename(filename, ".*")
35
46
  validate_name
36
47
 
48
+ unless (bad_keys = @config.keys - VALID_CONFIG_KEYS).empty?
49
+ raise ConfigurationError,
50
+ "Invalid pod configuration key(s): #{bad_keys.inspect}"
51
+ end
37
52
 
38
53
  unless @config.has_key?("containers")
39
54
  raise ConfigurationError,
@@ -100,6 +115,11 @@ module MobyDerp
100
115
  raise ConfigurationError,
101
116
  "container name #{name.inspect} is invalid (must contain only alphanumerics, underscores, and hyphens)"
102
117
  end
118
+
119
+ unless data.is_a?(Hash)
120
+ raise ConfigurationError,
121
+ "container data must be a hash"
122
+ end
103
123
  end
104
124
 
105
125
  begin
@@ -181,18 +201,23 @@ module MobyDerp
181
201
  "expose must be an array"
182
202
  end
183
203
 
184
- @expose.map!(&:to_s)
185
-
186
- @expose.each do |e|
204
+ @expose.map! do |e|
205
+ e = e.to_s
187
206
  unless e.is_a?(String) && e =~ %r{\A\d+(/(tcp|udp))?\z}
188
207
  raise ConfigurationError,
189
208
  "exposed ports must be integers, with an optional protocol specifier (got #{e.inspect})"
190
209
  end
191
210
 
211
+ if $1.nil?
212
+ e += "/tcp"
213
+ end
214
+
192
215
  if e.to_i < 1 || e.to_i > 65535
193
216
  raise ConfigurationError,
194
217
  "exposed port #{e} is out of range (expected 1-65535)"
195
218
  end
219
+
220
+ e
196
221
  end
197
222
  end
198
223
 
@@ -1,16 +1,21 @@
1
1
  require_relative "./config_file"
2
2
 
3
- require "safe_yaml"
4
-
5
3
  module MobyDerp
6
4
  class SystemConfig < ConfigFile
7
5
  attr_reader :mount_root, :port_whitelist, :network_name, :use_host_resolv_conf,
8
6
  :cpu_count, :cpu_bits
9
7
 
10
- def initialize(filename, moby_info, logger)
8
+ def initialize(config_data_or_filename, moby_info, logger)
11
9
  @logger = logger
12
10
 
13
- super(filename)
11
+ case config_data_or_filename
12
+ when String
13
+ super(config_data_or_filename)
14
+ when Hash
15
+ @config = stringify_keys(config_data_or_filename)
16
+ else
17
+ raise ArgumentError, "Unsupported type for config_data_or_filename parameter"
18
+ end
14
19
 
15
20
  @mount_root = @config["mount_root"]
16
21
  @port_whitelist = stringify_keys(@config["port_whitelist"] || {})
@@ -25,7 +25,6 @@ Gem::Specification.new do |s|
25
25
 
26
26
  s.add_runtime_dependency "docker-api"
27
27
  s.add_runtime_dependency "json-canonicalization"
28
- s.add_runtime_dependency "safe_yaml"
29
28
 
30
29
  s.add_development_dependency 'bundler'
31
30
  s.add_development_dependency 'deep_merge'
@@ -0,0 +1,28 @@
1
+ load test_helper
2
+
3
+ @test "Exposed ports" {
4
+ config_file <<-'EOF'
5
+ expose:
6
+ - 80
7
+ - "53/udp"
8
+ containers:
9
+ bob:
10
+ image: busybox:latest
11
+ command: sleep 600
12
+ common_labels:
13
+ moby-derp-smoke-test: ayup
14
+ EOF
15
+
16
+ run $MOBY_DERP_BIN $TEST_CONFIG_FILE
17
+
18
+ echo "status: $status"
19
+ echo "output: $output"
20
+
21
+ [ "$status" = "0" ]
22
+ container_running "mdst"
23
+ container_running "mdst.bob"
24
+
25
+ docker inspect mdst --format='{{.Config.ExposedPorts}}'
26
+ docker inspect mdst --format='{{.Config.ExposedPorts}}' | grep 'map.*53/udp:{}'
27
+ docker inspect mdst --format='{{.Config.ExposedPorts}}' | grep 'map.*80/tcp:{}'
28
+ }
@@ -0,0 +1,27 @@
1
+ load test_helper
2
+
3
+ @test "Core labels" {
4
+ config_file <<-'EOF'
5
+ root_labels:
6
+ foo: booblee
7
+ containers:
8
+ bob:
9
+ image: busybox:latest
10
+ command: sleep 1
11
+ common_labels:
12
+ moby-derp-smoke-test: ayup
13
+ EOF
14
+
15
+ run $MOBY_DERP_BIN $TEST_CONFIG_FILE
16
+
17
+ echo "status: $status"
18
+ echo "output: $output"
19
+
20
+ [ "$status" = "0" ]
21
+ container_running "mdst"
22
+ container_running "mdst.bob"
23
+
24
+ docker inspect mdst --format='{{.Config.Labels}}'
25
+ docker inspect mdst --format='{{.Config.Labels}}' | grep 'map.*foo:booblee'
26
+ ! docker inspect mdst.bob --format='{{.Config.Labels}}' | grep 'map.*foo:booblee'
27
+ }
@@ -23,7 +23,7 @@ EOF
23
23
  teardown() {
24
24
  for i in $(docker ps -a --format='{{.Names}}'); do
25
25
  if docker container inspect $i --format='{{.Config.Labels}}' | grep -q moby-derp-smoke-test; then
26
- docker rm -f $i
26
+ docker rm -f $i >/dev/null
27
27
  fi
28
28
  done
29
29
  }
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.3.3
4
+ version: 0.7.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: 2019-05-04 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
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: safe_yaml
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: bundler
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -208,20 +194,22 @@ files:
208
194
  - README.md
209
195
  - bin/moby-derp
210
196
  - example.yml
211
- - lib/freedom_patches/docker/image.rb
212
197
  - lib/moby_derp/config_file.rb
213
198
  - lib/moby_derp/container.rb
214
199
  - lib/moby_derp/container_config.rb
215
200
  - lib/moby_derp/error.rb
201
+ - lib/moby_derp/freedom_patches/docker/credential.rb
202
+ - lib/moby_derp/freedom_patches/docker/image.rb
216
203
  - lib/moby_derp/logging_helpers.rb
217
- - lib/moby_derp/moby_info.rb
218
204
  - lib/moby_derp/mount.rb
219
205
  - lib/moby_derp/pod.rb
220
206
  - lib/moby_derp/pod_config.rb
221
207
  - lib/moby_derp/system_config.rb
222
208
  - moby-derp.gemspec
209
+ - smoke_tests/exposed.bats
223
210
  - smoke_tests/minimal.bats
224
211
  - smoke_tests/no_file.bats
212
+ - smoke_tests/root_labels.bats
225
213
  - smoke_tests/test_helper.bash
226
214
  homepage: http://github.com/mpalmer/moby-derp
227
215
  licenses: []
@@ -241,7 +229,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
241
229
  - !ruby/object:Gem::Version
242
230
  version: '0'
243
231
  requirements: []
244
- rubygems_version: 3.0.1
232
+ rubygems_version: 3.0.3
245
233
  signing_key:
246
234
  specification_version: 4
247
235
  summary: A simple management system for a pod of moby containers
@@ -1,12 +0,0 @@
1
- module MobyDerp
2
- class MobyInfo
3
- attr_reader :cpu_count, :cpu_bits
4
-
5
- def initialize(info)
6
- @cpu_count = info["NCPU"]
7
- # As far as I can tell, the only 32-bit platform Moby supports is
8
- # armhf; if that turns out to be incorrect, amend the list below.
9
- @cpu_bits = %w{armhf}.include?(info["Architecture"]) ? 32 : 64
10
- end
11
- end
12
- end