docker-provider 0.0.1

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 (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +8 -0
  5. data/CHANGELOG.md +3 -0
  6. data/Gemfile +21 -0
  7. data/Gemfile.lock +125 -0
  8. data/Guardfile +6 -0
  9. data/LICENSE.txt +22 -0
  10. data/README.md +134 -0
  11. data/Rakefile +20 -0
  12. data/boxes/dummy/README.md +17 -0
  13. data/boxes/dummy/metadata.json +3 -0
  14. data/boxes/nginx/.gitignore +1 -0
  15. data/boxes/nginx/Dockerfile +4 -0
  16. data/boxes/nginx/README.md +25 -0
  17. data/boxes/nginx/Vagrantfile.sample +6 -0
  18. data/boxes/nginx/metadata.json +3 -0
  19. data/boxes/nginx/start +5 -0
  20. data/boxes/precise/.gitignore +1 -0
  21. data/boxes/precise/Dockerfile +42 -0
  22. data/boxes/precise/README.md +18 -0
  23. data/boxes/precise/Vagrantfile.sample +6 -0
  24. data/boxes/precise/metadata.json +3 -0
  25. data/development/Vagrantfile +91 -0
  26. data/docker-provider.gemspec +25 -0
  27. data/example/Vagrantfile +36 -0
  28. data/lib/docker-provider.rb +1 -0
  29. data/lib/docker-provider/action.rb +161 -0
  30. data/lib/docker-provider/action/check_running.rb +25 -0
  31. data/lib/docker-provider/action/create.rb +56 -0
  32. data/lib/docker-provider/action/created.rb +18 -0
  33. data/lib/docker-provider/action/destroy.rb +24 -0
  34. data/lib/docker-provider/action/forward_ports.rb +54 -0
  35. data/lib/docker-provider/action/is_running.rb +20 -0
  36. data/lib/docker-provider/action/message.rb +23 -0
  37. data/lib/docker-provider/action/share_folders.rb +63 -0
  38. data/lib/docker-provider/action/start.rb +18 -0
  39. data/lib/docker-provider/action/stop.rb +21 -0
  40. data/lib/docker-provider/config.rb +28 -0
  41. data/lib/docker-provider/driver.rb +114 -0
  42. data/lib/docker-provider/plugin.rb +24 -0
  43. data/lib/docker-provider/provider.rb +59 -0
  44. data/lib/docker-provider/version.rb +5 -0
  45. data/locales/en.yml +21 -0
  46. data/spec/acceptance/Vagrantfile +25 -0
  47. data/spec/acceptance/vagrant_ssh.bats +34 -0
  48. data/spec/acceptance/vagrant_up.bats +35 -0
  49. data/spec/spec_helper.rb +19 -0
  50. data/spec/support/unit_example_group.rb +39 -0
  51. data/spec/unit/driver_spec.rb +143 -0
  52. metadata +142 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ "provider": "docker"
3
+ }
@@ -0,0 +1,5 @@
1
+ #!/bin/bash
2
+
3
+ /etc/init.d/nginx start
4
+ # Make sure a SSH server is up so that Vagrant is able to SSH into it
5
+ /usr/sbin/sshd -D -e
@@ -0,0 +1 @@
1
+ Vagrantfile
@@ -0,0 +1,42 @@
1
+ # Base Vagrant box
2
+ #
3
+ # VERSION 0.0.1
4
+
5
+ FROM ubuntu:precise
6
+ MAINTAINER Fabio Rehm "fgrehm@gmail.com"
7
+
8
+ # Enable universe
9
+ RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
10
+
11
+ # Update things
12
+ RUN apt-get update && apt-get install openssh-server sudo curl -y && apt-get upgrade -y && apt-get clean
13
+
14
+ # Create and configure vagrant user
15
+ RUN useradd --create-home -s /bin/bash vagrant
16
+ WORKDIR /home/vagrant
17
+
18
+ # Configure SSH access
19
+ RUN mkdir -p /home/vagrant/.ssh
20
+ RUN echo "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key" > /home/vagrant/.ssh/authorized_keys
21
+ RUN chown -R vagrant: /home/vagrant/.ssh
22
+ RUN adduser vagrant sudo
23
+ RUN echo -n 'vagrant:vagrant' | chpasswd
24
+
25
+ # Enable passwordless sudo for users under the "sudo" group
26
+ RUN sed -i.bkp -e \
27
+ 's/%sudo\s\+ALL=(ALL\(:ALL\)\?)\s\+ALL/%sudo ALL=NOPASSWD:ALL/g' \
28
+ /etc/sudoers
29
+
30
+ # Thanks to http://docs.docker.io/en/latest/examples/running_ssh_service/
31
+ RUN mkdir /var/run/sshd
32
+
33
+ # Puppet
34
+ RUN wget http://apt.puppetlabs.com/puppetlabs-release-stable.deb -O /tmp/puppetlabs-release-stable.deb && \
35
+ dpkg -i /tmp/puppetlabs-release-stable.deb && \
36
+ apt-get update && \
37
+ apt-get install puppet puppet-common hiera facter virt-what -y --force-yes && \
38
+ rm -f /tmp/*.deb && \
39
+ apt-get clean
40
+
41
+ # Chef
42
+ RUN curl -L https://www.opscode.com/chef/install.sh -k | bash && apt-get clean
@@ -0,0 +1,18 @@
1
+ # Ubuntu Precise base box
2
+
3
+ This folder contains an example of a Dockerfile that builds an image ready for
4
+ usage with Vagrant. Please check out the [source](boxes/precise/Dockerfile)
5
+ for more information on building your own.
6
+
7
+ To turn this into a box:
8
+
9
+ ```
10
+ docker build -t myuser/vagrant-ubuntu:precise .
11
+ docker push myuser/vagrant-ubuntu:precise
12
+ sed 's/IMAGE/myuser\/vagrant-ubuntu:precise/' Vagrantfile.sample > Vagrantfile
13
+ tar cvzf precise.box ./metadata.json ./Vagrantfile
14
+ ```
15
+
16
+ This box works by using Vagrant's built-in `Vagrantfile` merging to setup defaults
17
+ for Docker. These defaults can easily be overwritten by higher-level Vagrantfiles
18
+ (such as project root Vagrantfiles).
@@ -0,0 +1,6 @@
1
+ Vagrant.configure("2") do |config|
2
+ config.vm.provider :docker do |docker|
3
+ docker.image = "IMAGE"
4
+ docker.cmd = ["/usr/sbin/sshd", "-D", "-e"]
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ {
2
+ "provider": "docker"
3
+ }
@@ -0,0 +1,91 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ Vagrant.require_plugin 'vagrant-cachier'
5
+ Vagrant.require_plugin 'vagrant-notify'
6
+ Vagrant.require_plugin 'vagrant-lxc'
7
+ Vagrant.require_plugin 'vagrant-pristine'
8
+ Vagrant.require_plugin 'vagrant-global-status'
9
+ Vagrant.require_plugin 'ventriloquist'
10
+
11
+ # Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
12
+ VAGRANTFILE_API_VERSION = "2"
13
+
14
+ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
15
+ config.vm.box = "raring64"
16
+ config.vm.synced_folder "../", "/vagrant", id: 'vagrant-root'
17
+
18
+ config.cache.auto_detect = true
19
+
20
+ config.vm.provider :lxc do |lxc, override|
21
+ # Required to boot nested containers
22
+ lxc.customize 'aa_profile', 'unconfined'
23
+ override.vm.box_url = 'http://bit.ly/vagrant-lxc-raring64-2013-10-23'
24
+ end
25
+
26
+ config.vm.provider :virtualbox do |vb, override|
27
+ vb.customize [ "modifyvm", :id, "--memory", 1536, "--cpus", "2" ]
28
+ override.vm.box_url = 'http://cloud-images.ubuntu.com/vagrant/raring/current/raring-server-cloudimg-amd64-vagrant-disk1.box'
29
+ override.vm.network :private_network, ip: "192.168.50.102"
30
+ end
31
+
32
+ # Required to boot nested containers
33
+ config.vm.provision :shell, inline: %[
34
+ if ! [ -f /etc/default/lxc ]; then
35
+ cat <<STR > /etc/default/lxc
36
+ LXC_AUTO="true"
37
+ USE_LXC_BRIDGE="true"
38
+ LXC_BRIDGE="lxcbr0"
39
+ LXC_ADDR="10.0.240.1"
40
+ LXC_NETMASK="255.255.255.0"
41
+ LXC_NETWORK="10.0.240.0/24"
42
+ LXC_DHCP_RANGE="10.0.240.2,10.0.240.254"
43
+ LXC_DHCP_MAX="253"
44
+ LXC_SHUTDOWN_TIMEOUT=120
45
+ STR
46
+ fi
47
+ ]
48
+
49
+ # Install docker on the machine (powered by Vocker)
50
+ config.vm.provision :docker do |docker|
51
+ docker.pull_images 'ubuntu:precise'
52
+ end
53
+
54
+ # Configure Ruby so that we can test the plugin from within the VM
55
+ config.vm.provision :ventriloquist do |env|
56
+ env.platforms << 'ruby:1.9.3'
57
+ end
58
+
59
+ config.vm.provision :shell, privileged: false, inline: %[
60
+ # Bundle!
61
+ cd /vagrant && bundle install
62
+
63
+ # Because we are lazy
64
+ if ! $(grep 'cd /vagrant' -q $HOME/.bashrc); then
65
+ echo 'alias be="bundle exec"' >> $HOME/.bashrc
66
+ echo 'alias vagrant="bundle exec vagrant"' >> $HOME/.bashrc
67
+ echo 'cd /vagrant' >> $HOME/.bashrc
68
+ fi
69
+
70
+ if ! [ -d $HOME/.vagrant.d/boxes ]; then
71
+ # This is a dummy base box "built" by hand
72
+ mkdir -p $HOME/.vagrant.d/boxes/dummy/docker
73
+ echo '{ "provider": "docker" }' > $HOME/.vagrant.d/boxes/dummy/docker/metadata.json
74
+ fi
75
+
76
+ # TODO: Get rid of this once Ventriloquist gets support for it:
77
+ # https://github.com/fgrehm/ventriloquist/issues/32
78
+ if ! [ -f /usr/local/bin/bats ]; then
79
+ git clone https://github.com/sstephenson/bats.git /tmp/bats
80
+ cd /tmp/bats && sudo ./install.sh /usr/local
81
+ rm -rf /tmp/bats
82
+ fi
83
+
84
+ if ! $(which bsdtar > /dev/null 2>/dev/null); then
85
+ sudo apt-get install bsdtar -y
86
+ fi
87
+
88
+ echo -n "\n\n----\n"
89
+ echo 'If this is the first time you are provisioning the VM, please `bundle exec vagrant reload` it ;)'
90
+ ]
91
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'docker-provider/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "docker-provider"
8
+ spec.version = VagrantPlugins::DockerProvider::VERSION
9
+ spec.authors = ["Fabio Rehm"]
10
+ spec.email = ["fgrehm@gmail.com"]
11
+ spec.description = %q{Experimental Docker provider for Vagrant}
12
+ spec.summary = spec.description
13
+ spec.homepage = "https://github.com/fgrehm/docker-provider"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ # TODO: spec.add_dependency 'docker-api', '~> 1.6.0'
25
+ end
@@ -0,0 +1,36 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ ENV['VAGRANT_DEFAULT_PROVIDER'] = 'docker'
5
+
6
+ # This is only needed if you are using the plugin from sources with bundler
7
+ Vagrant.require_plugin 'docker-provider'
8
+
9
+ # Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
10
+ VAGRANTFILE_API_VERSION = "2"
11
+
12
+ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
13
+ # This just fires up a container with a SSH server
14
+ config.vm.define 'dummy' do |node|
15
+ node.vm.box = 'dummy'
16
+ node.vm.box_url = 'http://bit.ly/vagrant-docker-dummy'
17
+
18
+ node.vm.provider :docker do |docker|
19
+ docker.image = 'fgrehm/vagrant-ubuntu:precise'
20
+ docker.cmd = ["/usr/sbin/sshd", "-D", "-e"]
21
+ end
22
+ end
23
+
24
+ # TODO: This is a container that gets provisioned with Puppet
25
+ config.vm.define 'precise' do |node|
26
+ node.vm.box = 'precise'
27
+ node.vm.box_url = 'http://bit.ly/vagrant-docker-precise'
28
+ end
29
+
30
+ # Custom start script
31
+ config.vm.define 'nginx' do |node|
32
+ node.vm.box = 'nginx'
33
+ node.vm.box_url = 'http://bit.ly/vagrant-docker-nginx'
34
+ node.vm.network "forwarded_port", guest: 80, host: 8080
35
+ end
36
+ end
@@ -0,0 +1 @@
1
+ require 'docker-provider/plugin'
@@ -0,0 +1,161 @@
1
+ require_relative 'action/check_running'
2
+ require_relative 'action/created'
3
+ require_relative 'action/create'
4
+ require_relative 'action/destroy'
5
+ require_relative 'action/forward_ports'
6
+ require_relative 'action/stop'
7
+ require_relative 'action/message'
8
+ require_relative 'action/is_running'
9
+ require_relative 'action/share_folders'
10
+ require_relative 'action/start'
11
+
12
+ module VagrantPlugins
13
+ module DockerProvider
14
+ module Action
15
+ # Shortcuts
16
+ Builtin = Vagrant::Action::Builtin
17
+ Builder = Vagrant::Action::Builder
18
+
19
+ # This action brings the "machine" up from nothing, including creating the
20
+ # container, configuring metadata, and booting.
21
+ def self.action_up
22
+ Builder.new.tap do |b|
23
+ b.use Builtin::ConfigValidate
24
+ b.use Builtin::Call, Created do |env, b2|
25
+ if !env[:result]
26
+ b2.use Builtin::HandleBoxUrl
27
+ # TODO: Find out where this fits into the process
28
+ # b2.use Builtin::EnvSet, :port_collision_repair => true
29
+ # b2.use Builtin::HandleForwardedPortCollisions
30
+ b2.use ShareFolders
31
+ b2.use ForwardPorts
32
+ # This will actually create and start, but that's fine
33
+ b2.use Create
34
+ b2.use action_boot
35
+ end
36
+ end
37
+ b.use action_start
38
+ end
39
+ end
40
+
41
+ # This action just runs the provisioners on the machine.
42
+ def self.action_provision
43
+ Builder.new.tap do |b|
44
+ b.use Builtin::ConfigValidate
45
+ b.use Builtin::Call, Created do |env1, b2|
46
+ if !env1[:result]
47
+ b2.use Message, :not_created
48
+ next
49
+ end
50
+
51
+ b2.use Builtin::Call, IsRunning do |env2, b3|
52
+ if !env2[:result]
53
+ b3.use Message, :not_running
54
+ next
55
+ end
56
+
57
+ b3.use Builtin::Provision
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ # This is the action that is primarily responsible for halting
64
+ # the virtual machine, gracefully or by force.
65
+ def self.action_halt
66
+ Builder.new.tap do |b|
67
+ b.use Builtin::Call, Created do |env, b2|
68
+ if env[:result]
69
+ # TODO: Make use of this once we figure out how to run dockers in machine mode
70
+ # b2.use Builtin::Call, Builtin::GracefulHalt, :stopped, :running do |env2, b3|
71
+ b2.use Stop
72
+ else
73
+ b2.use Message, :not_created
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ # This action is responsible for reloading the machine, which
80
+ # brings it down, sucks in new configuration, and brings the
81
+ # machine back up with the new configuration.
82
+ def self.action_reload
83
+ Builder.new.tap do |b|
84
+ b.use Builtin::Call, Created do |env1, b2|
85
+ if !env1[:result]
86
+ b2.use Message, :not_created
87
+ next
88
+ end
89
+
90
+ b2.use Builtin::ConfigValidate
91
+ b2.use action_halt
92
+ b2.use action_start
93
+ end
94
+ end
95
+ end
96
+
97
+ # This is the action that is primarily responsible for completely
98
+ # freeing the resources of the underlying virtual machine.
99
+ def self.action_destroy
100
+ Builder.new.tap do |b|
101
+ b.use Builtin::Call, Created do |env1, b2|
102
+ if !env1[:result]
103
+ b2.use Message, :not_created
104
+ next
105
+ end
106
+
107
+ b2.use Builtin::Call, Builtin::DestroyConfirm do |env2, b3|
108
+ if env2[:result]
109
+ b3.use Builtin::ConfigValidate
110
+ b3.use Builtin::EnvSet, :force_halt => true
111
+ b3.use action_halt
112
+ b3.use Destroy
113
+ b3.use Builtin::ProvisionerCleanup
114
+ else
115
+ b3.use Message, :will_not_destroy
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ # This is the action that will exec into an SSH shell.
123
+ def self.action_ssh
124
+ Builder.new.tap do |b|
125
+ b.use CheckRunning
126
+ b.use Builtin::SSHExec
127
+ end
128
+ end
129
+
130
+ # This is the action that will run a single SSH command.
131
+ def self.action_ssh_run
132
+ Builder.new.tap do |b|
133
+ b.use CheckRunning
134
+ b.use Builtin::SSHRun
135
+ end
136
+ end
137
+
138
+ def self.action_start
139
+ Builder.new.tap do |b|
140
+ b.use Builtin::ConfigValidate
141
+ b.use Builtin::Call, IsRunning do |env, b2|
142
+ # If the container is running, then our work here is done, exit
143
+ next if env[:result]
144
+
145
+ b2.use Message, :starting
146
+ b2.use action_boot
147
+ end
148
+ end
149
+ end
150
+
151
+ def self.action_boot
152
+ Builder.new.tap do |b|
153
+ b.use Builtin::Provision
154
+ # b.use Builtin::SetHostname
155
+ b.use Start
156
+ b.use Builtin::WaitForCommunicator
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,25 @@
1
+ module VagrantPlugins
2
+ module DockerProvider
3
+ module Action
4
+ class CheckRunning
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ if env[:machine].state.id == :not_created
11
+ raise Vagrant::Errors::VMNotCreatedError
12
+ end
13
+
14
+ if env[:machine].state.id == :created
15
+ raise Vagrant::Errors::VMNotRunningError
16
+ end
17
+
18
+ # Call the next if we have one (but we shouldn't, since this
19
+ # middleware is built to run with the Call-type middlewares)
20
+ @app.call(env)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,56 @@
1
+ module VagrantPlugins
2
+ module DockerProvider
3
+ module Action
4
+ class Create
5
+ def initialize(app, env)
6
+ @app = app
7
+ @@mutex ||= Mutex.new
8
+ end
9
+
10
+ def call(env)
11
+ @env = env
12
+ @machine = env[:machine]
13
+ @provider_config = @machine.provider_config
14
+ @machine_config = @machine.config
15
+ @driver = @machine.provider.driver
16
+
17
+ cid = ''
18
+ @@mutex.synchronize do
19
+ cid = @driver.create(create_params)
20
+ end
21
+
22
+ @machine.id = cid
23
+ @app.call(env)
24
+ end
25
+
26
+ def create_params
27
+ container_name = "#{@env[:root_path].basename.to_s}_#{@machine.name}"
28
+ container_name.gsub!(/[^-a-z0-9_]/i, "")
29
+ container_name << "_#{Time.now.to_i}"
30
+
31
+ {
32
+ image: @provider_config.image,
33
+ cmd: @provider_config.cmd,
34
+ ports: forwarded_ports,
35
+ name: container_name,
36
+ hostname: @machine_config.vm.hostname,
37
+ volumes: synced_folders
38
+ }
39
+ end
40
+
41
+ def forwarded_ports
42
+ @env[:forwarded_ports].map do |fp|
43
+ # TODO: Support for the protocol argument
44
+ "#{fp[:host]}:#{fp[:guest]}"
45
+ end.compact
46
+ end
47
+
48
+ def synced_folders
49
+ @env[:synced_folders].map do |sf|
50
+ "#{sf[:hostpath]}:#{sf[:guestpath]}"
51
+ end.compact
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end