moby-derp 0.3.1 → 0.5.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: 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