docker-provider 0.0.2 → 0.1.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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/Gemfile +7 -7
  4. data/Gemfile.lock +51 -40
  5. data/LICENSE.txt +1 -1
  6. data/README.md +130 -60
  7. data/Rakefile +6 -1
  8. data/boxes/dind/.gitignore +2 -0
  9. data/boxes/dind/Dockerfile +12 -0
  10. data/boxes/dind/README.md +10 -0
  11. data/boxes/{nginx → dind}/Vagrantfile.sample +2 -1
  12. data/boxes/{nginx → dind}/metadata.json +0 -0
  13. data/boxes/precise/Dockerfile +10 -9
  14. data/boxes/precise/Vagrantfile.sample +0 -1
  15. data/development/Vagrantfile +1 -9
  16. data/docker-provider.gemspec +1 -2
  17. data/example/Vagrantfile +11 -10
  18. data/lib/docker-provider.rb +2 -1
  19. data/lib/docker-provider/action.rb +17 -6
  20. data/lib/docker-provider/action/check_running.rb +1 -1
  21. data/lib/docker-provider/action/create.rb +14 -11
  22. data/lib/docker-provider/action/prepare_nfs_settings.rb +59 -0
  23. data/lib/docker-provider/action/prepare_nfs_valid_ids.rb +19 -0
  24. data/lib/docker-provider/config.rb +14 -7
  25. data/lib/docker-provider/driver.rb +30 -6
  26. data/lib/docker-provider/errors.rb +14 -0
  27. data/lib/docker-provider/plugin.rb +10 -3
  28. data/lib/docker-provider/provider.rb +1 -1
  29. data/lib/docker-provider/synced_folder.rb +20 -0
  30. data/lib/docker-provider/version.rb +1 -1
  31. data/locales/en.yml +13 -2
  32. data/spec/acceptance/provider/basic_spec.rb +94 -0
  33. data/spec/acceptance/provider/network_forwarded_port_spec.rb +29 -0
  34. data/spec/acceptance/provider/synced_folder_spec.rb +39 -0
  35. data/spec/acceptance/provisioner/chef_solo_spec.rb +37 -0
  36. data/spec/acceptance/provisioner/puppet_spec.rb +37 -0
  37. data/spec/acceptance/provisioner/shell_spec.rb +51 -0
  38. data/spec/acceptance/synced_folder/nfs_spec.rb +36 -0
  39. data/spec/unit/driver_spec.rb +70 -11
  40. data/vagrant-spec.config.rb +8 -0
  41. metadata +40 -29
  42. data/boxes/nginx/.gitignore +0 -1
  43. data/boxes/nginx/Dockerfile +0 -4
  44. data/boxes/nginx/README.md +0 -25
  45. data/boxes/nginx/start +0 -5
  46. data/lib/docker-provider/action/share_folders.rb +0 -63
  47. data/spec/acceptance/Vagrantfile +0 -25
  48. data/spec/acceptance/vagrant_ssh.bats +0 -34
  49. data/spec/acceptance/vagrant_up.bats +0 -35
@@ -0,0 +1,14 @@
1
+ require 'vagrant/errors'
2
+
3
+ module VagrantPlugins
4
+ module DockerProvider
5
+ module Errors
6
+ class ImageNotConfiguredError < Vagrant::Errors::VagrantError
7
+ error_key(:docker_provider_image_not_configured)
8
+ end
9
+ class NfsWithoutPrivilegedError < Vagrant::Errors::VagrantError
10
+ error_key(:docker_provider_nfs_without_privileged)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,6 +1,8 @@
1
- require_relative "version"
2
-
3
- require 'vagrant'
1
+ # TODO: Switch to Vagrant.require_version before 1.0.0
2
+ # see: https://github.com/mitchellh/vagrant/blob/bc55081e9ffaa6820113e449a9f76b293a29b27d/lib/vagrant.rb#L202-L228
3
+ unless Gem::Requirement.new('>= 1.4.0').satisfied_by?(Gem::Version.new(Vagrant::VERSION))
4
+ raise 'docker-provider requires Vagrant >= 1.4.0 in order to work!'
5
+ end
4
6
 
5
7
  I18n.load_path << File.expand_path(File.dirname(__FILE__) + '/../../locales/en.yml')
6
8
  I18n.reload!
@@ -19,6 +21,11 @@ module VagrantPlugins
19
21
  require_relative 'config'
20
22
  Config
21
23
  end
24
+
25
+ synced_folder(:docker) do
26
+ require File.expand_path("../synced_folder", __FILE__)
27
+ SyncedFolder
28
+ end
22
29
  end
23
30
  end
24
31
  end
@@ -25,7 +25,7 @@ module VagrantPlugins
25
25
  # we return nil.
26
26
  return nil if state == :not_created
27
27
 
28
- network = @driver.inspect(@machine.id)['NetworkSettings']
28
+ network = @driver.inspect_container(@machine.id)['NetworkSettings']
29
29
  ip = network['IPAddress']
30
30
 
31
31
  # If we were not able to identify the container's IP, we return nil
@@ -0,0 +1,20 @@
1
+ module VagrantPlugins
2
+ module DockerProvider
3
+ class SyncedFolder < Vagrant.plugin("2", :synced_folder)
4
+ def usable?(machine)
5
+ # These synced folders only work if the provider is Docker
6
+ machine.provider_name == :docker
7
+ end
8
+
9
+ def prepare(machine, folders, _opts)
10
+ # FIXME: Check whether the container has already been created with
11
+ # different synced folders and let the user know about it
12
+ folders.each do |id, data|
13
+ host_path = File.expand_path(data[:hostpath], machine.env.root_path)
14
+ guest_path = data[:guestpath]
15
+ machine.provider_config.volumes << "#{host_path}:#{guest_path}"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module DockerProvider
3
- VERSION = "0.0.2"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
@@ -17,5 +17,16 @@ en:
17
17
 
18
18
  errors:
19
19
  config:
20
- image_not_set: 'The base Docker image has not been set!'
21
- image_not_set: 'The Docker command has not been set!'
20
+ cmd_not_set: |-
21
+ The Docker command has not been set!
22
+
23
+ vagrant:
24
+ errors:
25
+ docker_provider_nfs_without_privileged: |-
26
+ You've configured a NFS synced folder but didn't enable privileged
27
+ mode for the container. Please set the `privileged` option to true
28
+ on the provider block from your Vagrantfile, recreate the container
29
+ and try again.
30
+
31
+ docker_provider_image_not_configured: |-
32
+ The base Docker image has not been set for the '%{name}' VM!
@@ -0,0 +1,94 @@
1
+ # This tests the basic functionality of a provider: that it can run
2
+ # a machine, provide SSH access, and destroy that machine.
3
+ shared_examples "provider/basic" do |provider, options|
4
+ if !options[:box]
5
+ raise ArgumentError,
6
+ "box option must be specified for provider: #{provider}"
7
+ end
8
+
9
+ include_context "acceptance"
10
+
11
+ before do
12
+ assert_execute("vagrant", "box", "add", "box", options[:box])
13
+ assert_execute("vagrant", "init", "box")
14
+ vagrantfile = environment.workdir.join('Vagrantfile')
15
+ # TODO: Can we just shell out to something?
16
+ new_vagrantfile = "Vagrant.require_plugin('docker-provider')\n#{vagrantfile.read}"
17
+ vagrantfile.open('w') { |f| f.puts(new_vagrantfile) }
18
+ end
19
+
20
+ after do
21
+ # Just always do this just in case
22
+ execute("vagrant", "destroy", "--force", log: false)
23
+ end
24
+
25
+ def assert_running
26
+ result = execute("vagrant", "ssh", "-c", "echo foo")
27
+ expect(result).to exit_with(0)
28
+ expect(result.stdout).to match(/foo\n$/)
29
+ end
30
+
31
+ def assert_not_running
32
+ result = execute("vagrant", "ssh", "-c", "echo foo")
33
+ expect(result).to exit_with(1)
34
+ end
35
+
36
+ =begin
37
+ TODO(mitchellh): These all exit with exit code 0. Unsure if bug.
38
+
39
+ it "can't halt before an up" do
40
+ expect(execute("vagrant", "halt")).to exit_with(1)
41
+ end
42
+
43
+ it "can't resume before an up" do
44
+ expect(execute("vagrant", "resume")).to exit_with(1)
45
+ end
46
+
47
+ it "can't suspend before an up" do
48
+ expect(execute("vagrant", "suspend")).to exit_with(1)
49
+ end
50
+ =end
51
+
52
+ context "after an up" do
53
+ before do
54
+ assert_execute("vagrant", "up", "--provider=#{provider}")
55
+ end
56
+
57
+ after do
58
+ assert_execute("vagrant", "destroy", "--force")
59
+ end
60
+
61
+ it "can manage machine lifecycle" do
62
+ status("Test: machine is running after up")
63
+ assert_running
64
+
65
+ if !options[:features].include?("!suspend")
66
+ status("Test: suspend")
67
+ assert_execute("vagrant", "suspend")
68
+
69
+ status("Test: ssh doesn't work during suspended state")
70
+ assert_not_running
71
+
72
+ status("Test: resume after suspend")
73
+ assert_execute("vagrant", "resume")
74
+ assert_running
75
+ else
76
+ status("Not testing 'suspend', provider doesn't support it")
77
+ end
78
+
79
+ if !options[:features].include?("!halt")
80
+ status("Test: halt")
81
+ assert_execute("vagrant", "halt")
82
+
83
+ status("Test: ssh doesn't work during halted state")
84
+ assert_not_running
85
+
86
+ status("Test: up after halt")
87
+ assert_execute("vagrant", "up")
88
+ assert_running
89
+ else
90
+ status("Not testing 'halt', provider doesn't support it")
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,29 @@
1
+ shared_examples "provider/network/forwarded_port" do |provider, options|
2
+ if !options[:box]
3
+ raise ArgumentError,
4
+ "box option must be specified for provider: #{provider}"
5
+ end
6
+
7
+ include_context "acceptance"
8
+
9
+ before do
10
+ environment.skeleton("network_forwarded_port")
11
+
12
+ vagrantfile = environment.workdir.join('Vagrantfile')
13
+ # TODO: Can we just shell out to something?
14
+ new_vagrantfile = "Vagrant.require_plugin('docker-provider')\n#{vagrantfile.read}"
15
+ vagrantfile.open('w') { |f| f.puts(new_vagrantfile) }
16
+
17
+ assert_execute("vagrant", "box", "add", "box", options[:box])
18
+ assert_execute("vagrant", "up", "--provider=#{provider}")
19
+ end
20
+
21
+ after do
22
+ assert_execute("vagrant", "destroy", "--force")
23
+ end
24
+
25
+ it "properly configures forwarded ports" do
26
+ status("Test: TCP forwarded port (default)")
27
+ assert_network("http://localhost:8080/", 8080)
28
+ end
29
+ end
@@ -0,0 +1,39 @@
1
+ # This tests that synced folders work with a given provider.
2
+ shared_examples "provider/synced_folder" do |provider, options|
3
+ if !options[:box]
4
+ raise ArgumentError,
5
+ "box option must be specified for provider: #{provider}"
6
+ end
7
+
8
+ include_context "acceptance"
9
+
10
+ before do
11
+ environment.skeleton("synced_folders")
12
+
13
+ vagrantfile = environment.workdir.join('Vagrantfile')
14
+ # TODO: Can we just shell out to something?
15
+ new_vagrantfile = "Vagrant.require_plugin('docker-provider')\n#{vagrantfile.read}"
16
+ vagrantfile.open('w') { |f| f.puts(new_vagrantfile) }
17
+
18
+ assert_execute("vagrant", "box", "add", "basic", options[:box])
19
+ assert_execute("vagrant", "up", "--provider=#{provider}")
20
+ end
21
+
22
+ after do
23
+ assert_execute("vagrant", "destroy", "--force")
24
+ end
25
+
26
+ # We put all of this in a single RSpec test so that we can test all
27
+ # the cases within a single VM rather than having to `vagrant up` many
28
+ # times.
29
+ it "properly configures synced folder types" do
30
+ status("Test: mounts the default /vagrant synced folder")
31
+ result = execute("vagrant", "ssh", "-c", "cat /vagrant/foo")
32
+ expect(result.exit_code).to eql(0)
33
+ expect(result.stdout).to match(/hello$/)
34
+
35
+ status("Test: doesn't mount a disabled folder")
36
+ result = execute("vagrant", "ssh", "-c", "test -d /foo")
37
+ expect(result.exit_code).to eql(1)
38
+ end
39
+ end
@@ -0,0 +1,37 @@
1
+ shared_examples "provider/provisioner/chef-solo" do |provider, options|
2
+ box = options[:box_chef] || options[:box]
3
+ if !box
4
+ raise ArgumentError,
5
+ "box_basic option must be specified for provider: #{provider}"
6
+ end
7
+
8
+ include_context "acceptance"
9
+
10
+ before do
11
+ environment.skeleton("provisioner_chef_solo")
12
+
13
+ vagrantfile = environment.workdir.join('Vagrantfile')
14
+ # TODO: Can we just shell out to something?
15
+ new_vagrantfile = "Vagrant.require_plugin('docker-provider')\n#{vagrantfile.read}"
16
+ vagrantfile.open('w') { |f| f.puts(new_vagrantfile) }
17
+
18
+ assert_execute("vagrant", "box", "add", "box", box)
19
+ assert_execute("vagrant", "up", "--provider=#{provider}")
20
+ end
21
+
22
+ after do
23
+ assert_execute("vagrant", "destroy", "--force")
24
+ end
25
+
26
+ it "provisions with chef-solo" do
27
+ status("Test: basic cookbooks and recipes")
28
+ result = execute("vagrant", "ssh", "-c", "cat /vagrant-chef-basic")
29
+ expect(result).to exit_with(0)
30
+ expect(result.stdout).to match(/basic$/)
31
+
32
+ status("Test: works with roles")
33
+ result = execute("vagrant", "ssh", "-c", "cat /vagrant-chef-basic-roles")
34
+ expect(result).to exit_with(0)
35
+ expect(result.stdout).to match(/basic-roles$/)
36
+ end
37
+ end
@@ -0,0 +1,37 @@
1
+ shared_examples "provider/provisioner/puppet" do |provider, options|
2
+ box = options[:box_puppet] || options[:box]
3
+ if !box
4
+ raise ArgumentError,
5
+ "box_basic option must be specified for provider: #{provider}"
6
+ end
7
+
8
+ include_context "acceptance"
9
+
10
+ before do
11
+ environment.skeleton("provisioner_puppet")
12
+
13
+ vagrantfile = environment.workdir.join('Vagrantfile')
14
+ # TODO: Can we just shell out to something?
15
+ new_vagrantfile = "Vagrant.require_plugin('docker-provider')\n#{vagrantfile.read}"
16
+ vagrantfile.open('w') { |f| f.puts(new_vagrantfile) }
17
+
18
+ assert_execute("vagrant", "box", "add", "box", box)
19
+ assert_execute("vagrant", "up", "--provider=#{provider}")
20
+ end
21
+
22
+ after do
23
+ assert_execute("vagrant", "destroy", "--force")
24
+ end
25
+
26
+ it "provisions with puppet" do
27
+ status("Test: basic manifests")
28
+ result = execute("vagrant", "ssh", "-c", "cat /vagrant-puppet-basic")
29
+ expect(result).to exit_with(0)
30
+ expect(result.stdout).to match(/basic$/)
31
+
32
+ status("Test: basic modules")
33
+ result = execute("vagrant", "ssh", "-c", "cat /vagrant-puppet-basic-modules")
34
+ expect(result).to exit_with(0)
35
+ expect(result.stdout).to match(/modules$/)
36
+ end
37
+ end
@@ -0,0 +1,51 @@
1
+ shared_examples "provider/provisioner/shell" do |provider, options|
2
+ if !options[:box]
3
+ raise ArgumentError,
4
+ "box_basic option must be specified for provider: #{provider}"
5
+ end
6
+
7
+ include_context "acceptance"
8
+
9
+ before do
10
+ environment.skeleton("provisioner_shell")
11
+
12
+ vagrantfile = environment.workdir.join('Vagrantfile')
13
+ # TODO: Can we just shell out to something?
14
+ new_vagrantfile = "Vagrant.require_plugin('docker-provider')\n#{vagrantfile.read}"
15
+ vagrantfile.open('w') { |f| f.puts(new_vagrantfile) }
16
+
17
+ assert_execute("vagrant", "box", "add", "box", options[:box])
18
+ assert_execute("vagrant", "up", "--provider=#{provider}")
19
+ end
20
+
21
+ after do
22
+ assert_execute("vagrant", "destroy", "--force")
23
+ end
24
+
25
+ it "provisions with the shell script" do
26
+ status("Test: inline script")
27
+ result = execute("vagrant", "ssh", "-c", "cat /foo")
28
+ expect(result).to exit_with(0)
29
+ expect(result.stdout).to match(/foo\n$/)
30
+
31
+ status("Test: script from path")
32
+ result = execute("vagrant", "ssh", "-c", "cat /vagrant-path")
33
+ expect(result).to exit_with(0)
34
+ expect(result.stdout).to match(/bar\n$/)
35
+
36
+ status("Test: script with args")
37
+ result = execute("vagrant", "ssh", "-c", "cat /vagrant-args")
38
+ expect(result).to exit_with(0)
39
+ expect(result.stdout).to match(/hello\ntwo words\n$/)
40
+
41
+ status("Test: privileged scripts")
42
+ result = execute("vagrant", "ssh", "-c", "cat /tmp/vagrant-user-root")
43
+ expect(result).to exit_with(0)
44
+ expect(result.stdout).to match(/root$/)
45
+
46
+ status("Test: non-privileged scripts")
47
+ result = execute("vagrant", "ssh", "-c", "cat /tmp/vagrant-user")
48
+ expect(result).to exit_with(0)
49
+ expect(result.stdout).to_not match(/root$/)
50
+ end
51
+ end
@@ -0,0 +1,36 @@
1
+ shared_examples "provider/synced_folder/nfs" do |provider, options|
2
+ if !options[:box]
3
+ raise ArgumentError,
4
+ "box option must be specified for provider: #{provider}"
5
+ end
6
+
7
+ include_context "acceptance"
8
+
9
+ before do
10
+ environment.skeleton("synced_folder_nfs")
11
+
12
+ vagrantfile = environment.workdir.join('Vagrantfile')
13
+ new_vagrantfile = "Vagrant.require_plugin('docker-provider')\n#{vagrantfile.read}"
14
+ new_vagrantfile.gsub!(/(config\.vm\.box = "box")/, "\\1\nconfig.vm.provider :docker do |docker|\ndocker.privileged = true\nend\n")
15
+ new_vagrantfile.gsub!(/(, type: "nfs")/, '\1, mount_options: ["rw", "vers=3", "tcp", "nolock"]')
16
+ vagrantfile.open('w') { |f| f.puts(new_vagrantfile) }
17
+
18
+ assert_execute("vagrant", "box", "add", "box", options[:box])
19
+ assert_execute("vagrant", "up", "--provider=#{provider}")
20
+ end
21
+
22
+ after do
23
+ assert_execute("vagrant", "destroy", "--force")
24
+ end
25
+
26
+ it "properly configures NFS" do
27
+ status("Test: mounts the NFS folder")
28
+ result = execute("vagrant", "ssh", "-c", "cat /vagrant-nfs/foo")
29
+ expect(result).to exit_with(0)
30
+ expect(result.stdout).to match(/hello$/)
31
+
32
+ status("Test: doesn't mount a disabled folder")
33
+ result = execute("vagrant", "ssh", "-c", "test -d /foo")
34
+ expect(result.exit_code).to eql(1)
35
+ end
36
+ end
@@ -12,12 +12,13 @@ describe VagrantPlugins::DockerProvider::Driver do
12
12
 
13
13
  describe '#create' do
14
14
  let(:params) { {
15
- image: 'jimi/hendrix:eletric-ladyland',
16
- cmd: ['play', 'voodoo-chile'],
17
- ports: '8080:80',
18
- volumes: '/host/path:guest/path',
19
- name: cid,
20
- hostname: 'jimi-hendrix'
15
+ image: 'jimi/hendrix:eletric-ladyland',
16
+ cmd: ['play', 'voodoo-chile'],
17
+ ports: '8080:80',
18
+ volumes: '/host/path:guest/path',
19
+ name: cid,
20
+ hostname: 'jimi-hendrix',
21
+ privileged: true
21
22
  } }
22
23
 
23
24
  before { subject.create(params) }
@@ -38,6 +39,10 @@ describe VagrantPlugins::DockerProvider::Driver do
38
39
  expect(cmd_executed).to match(/-v #{params[:volumes]} .+ #{Regexp.escape params[:image]}/)
39
40
  end
40
41
 
42
+ it 'is able to run a privileged container' do
43
+ expect(cmd_executed).to match(/-privileged .+ #{Regexp.escape params[:image]}/)
44
+ end
45
+
41
46
  it 'sets the hostname if specified' do
42
47
  expect(cmd_executed).to match(/-h #{params[:hostname]} #{Regexp.escape params[:image]}/)
43
48
  end
@@ -86,6 +91,18 @@ describe VagrantPlugins::DockerProvider::Driver do
86
91
  end
87
92
  end
88
93
 
94
+ describe '#privileged?' do
95
+ it 'identifies privileged containers' do
96
+ subject.stub(inspect_container: {'HostConfig' => {"Privileged" => true}})
97
+ expect(subject).to be_privileged(cid)
98
+ end
99
+
100
+ it 'identifies unprivileged containers' do
101
+ subject.stub(inspect_container: {'HostConfig' => {"Privileged" => false}})
102
+ expect(subject).to_not be_privileged(cid)
103
+ end
104
+ end
105
+
89
106
  describe '#start' do
90
107
  context 'when container is running' do
91
108
  before { subject.stub(running?: true) }
@@ -111,7 +128,7 @@ describe VagrantPlugins::DockerProvider::Driver do
111
128
  before { subject.stub(running?: true) }
112
129
 
113
130
  it 'stops the container' do
114
- subject.should_receive(:execute).with('docker', 'stop', cid)
131
+ subject.should_receive(:execute).with('docker', 'stop', '-t', '1', cid)
115
132
  subject.stop(cid)
116
133
  end
117
134
  end
@@ -120,24 +137,66 @@ describe VagrantPlugins::DockerProvider::Driver do
120
137
  before { subject.stub(running?: false) }
121
138
 
122
139
  it 'does not stop container' do
123
- subject.should_not_receive(:execute).with('docker', 'stop', cid)
140
+ subject.should_not_receive(:execute).with('docker', 'stop', '-t', '1', cid)
124
141
  subject.stop(cid)
125
142
  end
126
143
  end
127
144
  end
128
145
 
129
- describe '#inspect' do
146
+ describe '#rm' do
147
+ context 'when container has been created' do
148
+ before { subject.stub(created?: true) }
149
+
150
+ it 'removes the container' do
151
+ subject.should_receive(:execute).with('docker', 'rm', '-v', cid)
152
+ subject.rm(cid)
153
+ end
154
+ end
155
+
156
+ context 'when container has not been created' do
157
+ before { subject.stub(created?: false) }
158
+
159
+ it 'does not attempt to remove the container' do
160
+ subject.should_not_receive(:execute).with('docker', 'rm', '-v', cid)
161
+ subject.rm(cid)
162
+ end
163
+ end
164
+ end
165
+
166
+ describe '#inspect_container' do
130
167
  let(:data) { '[{"json": "value"}]' }
131
168
 
132
169
  before { subject.stub(execute: data) }
133
170
 
134
171
  it 'inspects the container' do
135
172
  subject.should_receive(:execute).with('docker', 'inspect', cid)
136
- subject.inspect(cid)
173
+ subject.inspect_container(cid)
137
174
  end
138
175
 
139
176
  it 'parses the json output' do
140
- expect(subject.inspect(cid)).to eq('json' => 'value')
177
+ expect(subject.inspect_container(cid)).to eq('json' => 'value')
178
+ end
179
+ end
180
+
181
+ describe '#all_containers' do
182
+ let(:containers) { "container1\ncontainer2" }
183
+
184
+ before { subject.stub(execute: containers) }
185
+
186
+ it 'returns an array of all known containers' do
187
+ subject.should_receive(:execute).with('docker', 'ps', '-a', '-q', '-notrunc')
188
+ expect(subject.all_containers).to eq(['container1', 'container2'])
189
+ end
190
+ end
191
+
192
+ describe '#docker_bridge_ip' do
193
+ let(:containers) { " inet 123.456.789.012/16 " }
194
+
195
+ before { subject.stub(execute: containers) }
196
+
197
+ it 'returns an array of all known containers' do
198
+ subject.should_receive(:execute).with('/sbin/ip', '-4', 'addr', 'show', 'scope', 'global', 'docker0')
199
+ expect(subject.docker_bridge_ip).to eq('123.456.789.012')
141
200
  end
142
201
  end
143
202
  end