moby-derp 0.3.1 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa8c78f203aa3fb7ed760ae7936d4ed9217b6115a575dbd12750fc6f593255e1
4
- data.tar.gz: 88fb2d48ab4f6fa6548dee35bde129b1335243689ef535336397cdcc958c6d47
3
+ metadata.gz: 99faf7a4a2ccef6a30df32e08d424bf89c5693278100484a75e21276136e6a3a
4
+ data.tar.gz: 379c96e91a43e3b19db58d0e61d1324749969f58a2946a72f687429cda959f34
5
5
  SHA512:
6
- metadata.gz: 33122f5119bc621fb16352c0b87adb63ff0a22b441f185133afc833118303f97b1c48ae9cc82f72719f4bc1360c773e42ddc381bc6b143ae9438700e1e558c72
7
- data.tar.gz: 1d20c21089923a1ce19580d36049e6e2462c4473a89b15ba7c6c23074f953ff15b4b635c434eb7883268fff8b40f91cfed5c2dd8cc44d52072b83bec2bfc5a91
6
+ metadata.gz: 6d7b1071d6a38f8aa880ad7287c7355460a32dc4a66250e13bcec612d1f11ee91530d2cfedbba0bb4e8bdf54f5784fbaac00f807a46a967a35ddf45193feb6a6
7
+ data.tar.gz: ef1b7425e29551844fe383159a19010cc611ffc8dc07566f4c7e30afa4d3d02882692a3beaed35d6490263d51e093decd662e59b9e0169f177f2c221eb9079c4
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
@@ -11,7 +11,7 @@ if ARGV.length != 1
11
11
  exit 1
12
12
  end
13
13
 
14
- logger = Logger.new($stdout)
14
+ logger = Logger.new($stderr)
15
15
  logger.formatter = ->(s, t, p, m) { "#{m}\n" }
16
16
 
17
17
  case ENV["MOBY_DERP_LOG_LEVEL"]
@@ -44,6 +44,8 @@ rescue MobyDerp::ConfigurationError => ex
44
44
  exit 1
45
45
  end
46
46
 
47
+ Docker.options = { read_timeout: 86400 }
48
+
47
49
  pod = MobyDerp::Pod.new(pod_config)
48
50
 
49
51
  begin
@@ -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"
@@ -71,6 +71,7 @@ module MobyDerp
71
71
  }
72
72
  }
73
73
  end
74
+ params["ExposedPorts"] = Hash[@pod.expose.map { |ex| [ex, {}] }]
74
75
  else
75
76
  params["HostConfig"] = {
76
77
  "NetworkMode" => "container:#{@pod.root_container_id}",
@@ -126,7 +127,9 @@ module MobyDerp
126
127
  params["Labels"] = @pod.common_labels.merge(@config.labels)
127
128
  params["Labels"]["org.hezmatt.moby-derp.pod-name"] = @pod.name
128
129
 
129
- unless @root_container
130
+ if @root_container
131
+ params["Labels"] = @pod.root_labels.merge(params["Labels"])
132
+ else
130
133
  params["Labels"]["org.hezmatt.moby-derp.root-container-id"] = @pod.root_container_id
131
134
  end
132
135
  end
@@ -190,7 +193,7 @@ module MobyDerp
190
193
  def mount_structure(mount)
191
194
  {
192
195
  "Type" => "bind",
193
- "Source" => "#{@pod.mount_root}/#{mount.source}",
196
+ "Source" => mount.source[0] == "/" ? mount.source : "#{@pod.mount_root}/#{mount.source}",
194
197
  "Target" => mount.target,
195
198
  "ReadOnly" => mount.readonly,
196
199
  }
@@ -3,6 +3,7 @@ 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
@@ -66,7 +67,10 @@ module MobyDerp
66
67
  def validate_command
67
68
  case @command
68
69
  when String
69
- true
70
+ # Despite the Docker Engine API spec saying you can pass a string,
71
+ # if you do it doesn't get parsed into arguments... so that's pretty
72
+ # fucking useless.
73
+ @command = Shellwords.split(@command)
70
74
  when Array
71
75
  unless @command.all? { |c| String === c }
72
76
  raise ConfigurationError, "all elements of the command array must be strings"
@@ -48,6 +48,10 @@ module MobyDerp
48
48
  @config.common_labels
49
49
  end
50
50
 
51
+ def root_labels
52
+ @config.root_labels
53
+ end
54
+
51
55
  def common_environment
52
56
  @config.common_environment
53
57
  end
@@ -68,6 +72,10 @@ module MobyDerp
68
72
  @config.hostname
69
73
  end
70
74
 
75
+ def expose
76
+ @config.expose
77
+ end
78
+
71
79
  private
72
80
 
73
81
  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,
@@ -181,18 +196,23 @@ module MobyDerp
181
196
  "expose must be an array"
182
197
  end
183
198
 
184
- @expose.map!(&:to_s)
185
-
186
- @expose.each do |e|
199
+ @expose.map! do |e|
200
+ e = e.to_s
187
201
  unless e.is_a?(String) && e =~ %r{\A\d+(/(tcp|udp))?\z}
188
202
  raise ConfigurationError,
189
203
  "exposed ports must be integers, with an optional protocol specifier (got #{e.inspect})"
190
204
  end
191
205
 
206
+ if $1.nil?
207
+ e += "/tcp"
208
+ end
209
+
192
210
  if e.to_i < 1 || e.to_i > 65535
193
211
  raise ConfigurationError,
194
212
  "exposed port #{e} is out of range (expected 1-65535)"
195
213
  end
214
+
215
+ e
196
216
  end
197
217
  end
198
218
 
@@ -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.1
4
+ version: 0.5.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-03 00:00:00.000000000 Z
11
+ date: 2020-06-10 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
@@ -214,14 +200,15 @@ files:
214
200
  - lib/moby_derp/container_config.rb
215
201
  - lib/moby_derp/error.rb
216
202
  - lib/moby_derp/logging_helpers.rb
217
- - lib/moby_derp/moby_info.rb
218
203
  - lib/moby_derp/mount.rb
219
204
  - lib/moby_derp/pod.rb
220
205
  - lib/moby_derp/pod_config.rb
221
206
  - lib/moby_derp/system_config.rb
222
207
  - moby-derp.gemspec
208
+ - smoke_tests/exposed.bats
223
209
  - smoke_tests/minimal.bats
224
210
  - smoke_tests/no_file.bats
211
+ - smoke_tests/root_labels.bats
225
212
  - smoke_tests/test_helper.bash
226
213
  homepage: http://github.com/mpalmer/moby-derp
227
214
  licenses: []
@@ -241,7 +228,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
241
228
  - !ruby/object:Gem::Version
242
229
  version: '0'
243
230
  requirements: []
244
- rubygems_version: 3.0.1
231
+ rubygems_version: 3.0.3
245
232
  signing_key:
246
233
  specification_version: 4
247
234
  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