docker-api 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.cane +0 -0
  2. data/.gitignore +3 -0
  3. data/Gemfile +3 -0
  4. data/README.md +215 -0
  5. data/Rakefile +16 -0
  6. data/docker-api.gemspec +27 -0
  7. data/lib/docker.rb +60 -0
  8. data/lib/docker/connection.rb +65 -0
  9. data/lib/docker/container.rb +54 -0
  10. data/lib/docker/error.rb +23 -0
  11. data/lib/docker/image.rb +73 -0
  12. data/lib/docker/model.rb +88 -0
  13. data/lib/docker/multipart.rb +30 -0
  14. data/lib/docker/version.rb +3 -0
  15. data/spec/docker/connection_spec.rb +67 -0
  16. data/spec/docker/container_spec.rb +529 -0
  17. data/spec/docker/image_spec.rb +379 -0
  18. data/spec/docker_spec.rb +58 -0
  19. data/spec/spec_helper.rb +14 -0
  20. data/spec/support/vcr.rb +11 -0
  21. data/spec/vcr/Docker/_info/returns_the_info_as_a_Hash.yml +31 -0
  22. data/spec/vcr/Docker/_version/returns_the_version_as_a_Hash.yml +31 -0
  23. data/spec/vcr/Docker_Container/_all/when_the_HTTP_response_is_a_200/materializes_each_Container_into_a_Docker_Container.yml +333 -0
  24. data/spec/vcr/Docker_Container/_attach/when_the_Container_has_been_created/when_the_HTTP_response_status_is_200/yields_each_chunk.yml +81 -0
  25. data/spec/vcr/Docker_Container/_changes/when_the_Container_has_been_created/when_the_HTTP_response_status_is_200/returns_the_changes_as_an_array.yml +115 -0
  26. data/spec/vcr/Docker_Container/_commit/when_the_Container_has_been_created/when_the_HTTP_response_status_is_200/creates_a_new_Image_from_the_Container_s_changes.yml +87 -0
  27. data/spec/vcr/Docker_Container/_create_/when_the_Container_does_not_yet_exist_and_the_body_is_a_Hash/when_the_HTTP_request_returns_a_200/sets_the_id.yml +31 -0
  28. data/spec/vcr/Docker_Container/_export/when_the_Container_has_been_created/when_the_HTTP_response_status_is_200/yields_each_chunk.yml +97 -0
  29. data/spec/vcr/Docker_Container/_json/when_the_Container_has_been_created/when_the_HTTP_response_status_is_200/returns_the_description_as_a_Hash.yml +59 -0
  30. data/spec/vcr/Docker_Container/_kill/when_the_Container_has_been_created/when_the_HTTP_response_status_is_204/kills_the_container.yml +232 -0
  31. data/spec/vcr/Docker_Container/_restart/when_the_Container_has_been_created/when_the_HTTP_response_status_is_204/restarts_the_container.yml +201 -0
  32. data/spec/vcr/Docker_Container/_start/when_the_Container_has_been_created/when_the_HTTP_response_status_is_200/starts_the_container.yml +89 -0
  33. data/spec/vcr/Docker_Container/_stop/when_the_Container_has_been_created/when_the_HTTP_response_status_is_204/stops_the_container.yml +259 -0
  34. data/spec/vcr/Docker_Container/_wait/when_the_Container_has_been_created/when_the_HTTP_response_status_is_200/waits_for_the_command_to_finish.yml +87 -0
  35. data/spec/vcr/Docker_Image/_all/when_the_HTTP_response_is_a_200/materializes_each_Container_into_a_Docker_Container.yml +59 -0
  36. data/spec/vcr/Docker_Image/_build/with_a_valid_Dockerfile/builds_an_image.yml +45 -0
  37. data/spec/vcr/Docker_Image/_build/with_an_invalid_Dockerfile/throws_a_UnexpectedResponseError.yml +38 -0
  38. data/spec/vcr/Docker_Image/_create_/when_the_Image_does_not_yet_exist_and_the_body_is_a_Hash/when_the_HTTP_request_returns_a_200/sets_the_id.yml +31 -0
  39. data/spec/vcr/Docker_Image/_history/when_the_Image_has_been_created/when_the_HTTP_response_status_is_200/returns_the_history_of_the_Image.yml +59 -0
  40. data/spec/vcr/Docker_Image/_insert/when_the_Image_has_been_created/when_the_HTTP_response_status_is_200/inserts_the_file.yml +59 -0
  41. data/spec/vcr/Docker_Image/_json/when_the_Image_has_been_created/when_the_HTTP_response_status_is_200/returns_additional_information_about_image_image.yml +60 -0
  42. data/spec/vcr/Docker_Image/_remove/when_the_Image_has_been_created/when_the_HTTP_response_status_is_204/nils_out_the_id.yml +59 -0
  43. data/spec/vcr/Docker_Image/_search/when_the_HTTP_response_is_a_200/materializes_each_Container_into_a_Docker_Container.yml +64 -0
  44. data/spec/vcr/Docker_Image/_tag/when_the_Image_has_been_created/when_the_HTTP_response_status_is_200/tags_the_image_with_the_repo_name.yml +59 -0
  45. metadata +281 -0
data/.cane ADDED
File without changes
@@ -0,0 +1,3 @@
1
+ .DS_Store
2
+ *.swp
3
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,215 @@
1
+ docker-api
2
+ ==========
3
+
4
+ This gem provides an object-oriented interface to the [Docker Remote API](http://docs.docker.io/en/latest/api/docker_remote_api_v1.2/). Every method listed there is implemented, with the exception of attaching to the STDIN of a Container. At the time of this writing, docker-api is meant to interface with Docker version 0.4.0.
5
+
6
+ Installation
7
+ ------------
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'docker-api'
13
+ ```
14
+
15
+ And then run:
16
+
17
+ ```shell
18
+ $ bundle install
19
+ ```
20
+
21
+ Alternatively, if you wish to just use the gem in a script, you can run:
22
+
23
+ ```shell
24
+ $ gem install docker-api
25
+ ```
26
+
27
+ Finally, just add `require 'docker'` to the top of the file using this gem.
28
+
29
+ Usage
30
+ -----
31
+
32
+ docker-api is designed to be very lightweight. Almost no state is cached (aside from id's which are immutable) to ensure that each method call's information is up to date. As such, just about every extrenal method represents an API call.
33
+
34
+ ## Starting up
35
+
36
+ Follow the [installation instructions](http://www.docker.io/gettingstarted/), and then run:
37
+
38
+ ```shell
39
+ $ sudo docker -d
40
+ ```
41
+
42
+ This will daemonize Docker so that it can be used for the remote API calls.
43
+
44
+ If you're running Docker locally, there is no setup to do in Ruby. If you're not, you'll have to point the gem to your server. For example:
45
+
46
+ ```ruby
47
+ Docker.url = 'http://example.com'
48
+ Docker.options = { :port => 5422 }
49
+ ```
50
+
51
+ Two things to note here. The first is that this gem uses [excon](http://www.github.com/geemus/excon), so any of the options that are valid for `Excon.new` are alse valid for `Docker.options`. Second, by default Docker runs on port 4243. The gem will assume you want to connnect to port 4243 unless you specify otherwise.
52
+
53
+ ## Global calls
54
+
55
+ All of the following examples require a connection to a Docker server. See the <a href="#starting-up">Starting up</a> section above for more information.
56
+
57
+ ```ruby
58
+ require 'docker'
59
+ # => true
60
+
61
+ Docker.version
62
+ # => { 'Version' => '0.4.0', 'GoVersion' => 'go1.0.3' }
63
+
64
+ Docker.info
65
+ # => { "Debug" => false, "Containers" => 187, "Images" => 196, "NFd" => 10, "NGoroutines" => 9, "MemoryLimit" => true }
66
+
67
+ Docker.authenticate!('username' => 'docker-fan-boi', 'password' => 'i<3docker', 'email' => 'dockerboy22@aol.com')
68
+ # => true
69
+ ```
70
+
71
+ ## Images
72
+ Just about every method here has a one-to-one mapping with the [Images](http://docs.docker.io/en/latest/api/docker_remote_api_v1.2/#images) section of the API. If an API call accepts query parameters, these can be passed as an Hash to it's corresponding method.
73
+
74
+ ```ruby
75
+ require 'docker'
76
+ # => true
77
+
78
+ # Instantiate a new Image. Note that this does NOT create the Image.
79
+ image = Docker::Image.new
80
+ # => Docker::Image { :id => , :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }
81
+
82
+ # Test if the Image is created.
83
+ image.created?
84
+ # => false
85
+
86
+ # Create the Image.
87
+ image.create!('fromRepo' => 'base', 'fromSrc' => '-')
88
+ # => Docker::Image { :id => ae7ffbcd1, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }
89
+
90
+ image.created?
91
+ # => true
92
+
93
+ # Insert a file into an Image.
94
+ image.insert('path' => '/usr', 'url' => '/home/user/.vimrc')
95
+ # => { 'Id' => '' }
96
+
97
+ # Tag an Image.
98
+ image.tag('repo' => 'base2', 'force' => true)
99
+ # => nil
100
+
101
+ # Get more information about the Image.
102
+ image.json
103
+ # => {"id"=>"67859327bf22ef8b5b9b4a6781f72b2015acd894fa03ce07e0db7af170ba468c", "comment"=>"Imported from -", "created"=>"2013-06-19T18:42:58.287944526-04:00", "container_config"=>{"Hostname"=>"", "User"=>"", "Memory"=>0, "MemorySwap"=>0, "CpuShares"=>0, "AttachStdin"=>false, "AttachStdout"=>false, "AttachStderr"=>false, "PortSpecs"=>nil, "Tty"=>false, "OpenStdin"=>false, "StdinOnce"=>false, "Env"=>nil, "Cmd"=>nil, "Dns"=>nil, "Image"=>"", "Volumes"=>nil, "VolumesFrom"=>""}, "docker_version"=>"0.4.0", "architecture"=>"x86_64"}
104
+
105
+ # View the history of the Image.
106
+ image.history
107
+ # => [{"Id"=>"67859327bf22", "Created"=>1371681778}]
108
+
109
+ # Remove the Image from the server.
110
+ image.remove
111
+ # => true
112
+
113
+ image.created?
114
+ # => false
115
+
116
+ # Load all Images on your Docker server.
117
+ Docker::Image.all
118
+ # => [Docker::Image { :id => b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }, Docker::Image { :id => 8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }]
119
+
120
+ # Search the Docker registry.
121
+ Docker::Image.search('term' => 'sshd')
122
+ # => [Docker::Image { :id => cespare/sshd, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }, Docker::Image { :id => johnfuller/sshd, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }, Docker::Image { :id => dhrp/mongodb-sshd, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }, Docker::Image { :id => rayang2004/sshd, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }, Docker::Image { :id => dhrp/sshd, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }, Docker::Image { :id => toorop/daemontools-sshd, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }, Docker::Image { :id => toorop/daemontools-sshd-nginx, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }, Docker::Image { :id => toorop/daemontools-sshd-nginx-php-fpm, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }, Docker::Image { :id => mbkan/lamp, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }, Docker::Image { :id => toorop/golang, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }, Docker::Image { :id => wma55/u1210sshd, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }, Docker::Image { :id => jdswinbank/sshd, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }, Docker::Image { :id => vgauthier/sshd, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }]
123
+
124
+ # Create an Image from a Dockerfile.
125
+ Docker::Image.build("from base\nrun touch /test")
126
+ # => Docker::Image { :id => b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }
127
+ ```
128
+
129
+ ## Containers
130
+ Much like the Images, this object also has a one-to-one mapping with the [Containers](http://docs.docker.io/en/latest/api/docker_remote_api_v1.2/#containers) section of the API.
131
+
132
+ ```ruby
133
+ require 'docker'
134
+
135
+ # Instantiate a new Container.
136
+ container = Docker::Container.new
137
+ # => Docker::Container { :id => , :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }
138
+
139
+ # Test if the has been created.
140
+ container.created?
141
+ # => false
142
+
143
+ # Create the Container.
144
+ container.create!('Cmd' => ['ls'], 'Image' => 'base')
145
+ # => Docker::Container { :id => 492510dd38e4, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }
146
+
147
+ container.created?
148
+ # => true
149
+
150
+ # Get more information about the Container.
151
+ container.json
152
+ # => {"Id"=>"492510dd38e4da7703f36dfccd013de672b8250f57f59d1555ced647766b5e82", "Created"=>"2013-06-20T10:46:02.897548-04:00", "Path"=>"ls", "Args"=>[], "Config"=>{"Hostname"=>"492510dd38e4", "User"=>"", "Memory"=>0, "MemorySwap"=>0, "CpuShares"=>0, "AttachStdin"=>false, "AttachStdout"=>false, "AttachStderr"=>false, "PortSpecs"=>nil, "Tty"=>false, "OpenStdin"=>false, "StdinOnce"=>false, "Env"=>nil, "Cmd"=>["ls"], "Dns"=>nil, "Image"=>"base", "Volumes"=>nil, "VolumesFrom"=>""}, "State"=>{"Running"=>false, "Pid"=>0, "ExitCode"=>0, "StartedAt"=>"0001-01-01T00:00:00Z", "Ghost"=>false}, "Image"=>"b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc", "NetworkSettings"=>{"IpAddress"=>"", "IpPrefixLen"=>0, "Gateway"=>"", "Bridge"=>"", "PortMapping"=>nil}, "SysInitPath"=>"/usr/bin/docker", "ResolvConfPath"=>"/etc/resolv.conf", "Volumes"=>nil}
153
+
154
+ # Start running the Container.
155
+ container.start
156
+ # => nil
157
+
158
+ # Stop running the Container.
159
+ container.stop
160
+ # => nil
161
+
162
+ # Restart the Container.
163
+ container.restart
164
+ # => nil
165
+
166
+ # Kill the command running in the Container.
167
+ container.kill
168
+ # => nil
169
+
170
+ # Export a Container. Since an export is typically at least 300M, chunks of the
171
+ # export are yielded instead of just returning the whole thing.
172
+ File.open('export.tar.gz', 'w') do |f|
173
+ container.export { |chunk| file.write(chunk) }
174
+ end
175
+ # => nil
176
+
177
+ # Inspect a Container's changes to the file system.
178
+ container.changes
179
+ # => [{'Path'=>'/dev', 'Kind'=>0}, {'Path'=>'/dev/kmsg', 'Kind'=>1}]
180
+
181
+ # Wait for the current command to finish executing.
182
+ container.wait
183
+ # => {'StatusCode'=>0}
184
+
185
+ # Attach to the Container. Currently, the below options are the only valid ones.
186
+ container.attach(:stream => true, :stdout => true, :stderr => true, :logs => true)
187
+ # => "bin\nboot\ndev\netc\nhome\nlib\nlib64\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nselinux\nsrv\nsys\ntmp\nusr\nvar"
188
+
189
+ # Create an Image from a Container's changes.
190
+ container.commit
191
+ # => Docker::Image { :id => eaeb8d00efdf, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }
192
+
193
+ # Request all of the Containers. By default, will only return the running Containers.
194
+ Docker::Container.all(:all => true)
195
+ # => [Docker::Container { :id => , :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }]
196
+ ```
197
+
198
+ ## Connecting to Multiple Servers
199
+
200
+ By default, each object connects to the connection specified by `Docker.connection`. If you need to connect to multiple servers, you can do so by specifying the connection on `#new` or in the utilizing class method. Examples:
201
+
202
+ ```ruby
203
+ require 'docker'
204
+
205
+ Docker::Container.new(:connection => Docker::Connection.new(:url => 'http://example.com'))
206
+ Docker::Container.all({}, Docker::Connection.new(:url => 'http://example.com'))
207
+
208
+ Docker::Image.new(:connection => Docker::Connection.new(:url => 'http://example.com'))
209
+ Docker::Image.all({}, Docker::Connection.new(:url => 'http://example.com'))
210
+ Docker::Image.build('from base', Docker::Connection.new(:url => 'http://example.com'))
211
+ Docker::Image.build({ :term => 'sshd' }, Docker::Connection.new(:url => 'http://example.com'))
212
+ ```
213
+
214
+ ## Known Issues
215
+ - `Docker::Container#attach` cannot attach to STDIN
@@ -0,0 +1,16 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
+
3
+ require 'rake'
4
+ require 'docker'
5
+ require 'rspec/core/rake_task'
6
+ require 'cane/rake_task'
7
+
8
+ task :default => [:spec, :quality]
9
+
10
+ RSpec::Core::RakeTask.new do |t|
11
+ t.pattern = 'spec/**/*_spec.rb'
12
+ end
13
+
14
+ Cane::RakeTask.new(:quality) do |cane|
15
+ cane.canefile = '.cane'
16
+ end
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/docker/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Swipely, Inc."]
6
+ gem.email = %w{tomhulihan@swipely.com bright@swipely.com}
7
+ gem.description = %q{A simple REST client for the Docker Remote API}
8
+ gem.summary = %q{A simple REST client for the Docker Remote API}
9
+ gem.homepage = 'https://github.com/swipely/docker-api'
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "docker-api"
15
+ gem.require_paths = %w{lib}
16
+ gem.version = Docker::VERSION
17
+ gem.add_dependency 'excon', '>= 0.22.0'
18
+ gem.add_dependency 'json'
19
+ gem.add_dependency 'i18n'
20
+ gem.add_dependency 'multipart-post'
21
+ gem.add_development_dependency 'rake'
22
+ gem.add_development_dependency 'rspec'
23
+ gem.add_development_dependency 'cane'
24
+ gem.add_development_dependency 'pry'
25
+ gem.add_development_dependency 'webmock', '>= 1.11.0'
26
+ gem.add_development_dependency 'vcr', '>= 2.4.0'
27
+ end
@@ -0,0 +1,60 @@
1
+ require 'cgi'
2
+ require 'json'
3
+ require 'excon'
4
+ require 'net/http/post/multipart'
5
+
6
+ # The top-level module for this gem. It's purpose is to hold global
7
+ # configuration variables that are used as defaults in other classes.
8
+ module Docker
9
+ class << self
10
+ def url
11
+ @url ||= 'http://localhost'
12
+ end
13
+
14
+ def options
15
+ @options ||= { :port => 4243 }
16
+ end
17
+
18
+ def url=(new_url)
19
+ @url = new_url
20
+ reset_connection!
21
+ end
22
+
23
+ def options=(new_options)
24
+ @options = { :port => 4243 }.merge(new_options)
25
+ reset_connection!
26
+ end
27
+
28
+ def connection
29
+ @connection ||= Connection.new(url, options)
30
+ end
31
+
32
+ def reset_connection!
33
+ @connection = nil
34
+ end
35
+
36
+ # Get the version of Go, Docker, and optionally the Git commit.
37
+ def version
38
+ connection.json_request(:get, '/version')
39
+ end
40
+
41
+ # Get more information about the Docker server.
42
+ def info
43
+ connection.json_request(:get, '/info')
44
+ end
45
+
46
+ # Login to the Docker registry.
47
+ def authenticate!(options = {})
48
+ connection.post(:path => '/auth', :body => options)
49
+ true
50
+ end
51
+ end
52
+ end
53
+
54
+ require 'docker/version'
55
+ require 'docker/error'
56
+ require 'docker/connection'
57
+ require 'docker/model'
58
+ require 'docker/multipart'
59
+ require 'docker/container'
60
+ require 'docker/image'
@@ -0,0 +1,65 @@
1
+ # This class represents a Connection to a Docker server. The Connection is
2
+ # immutable in that once the url and options is set they cannot be changed.
3
+ class Docker::Connection
4
+ include Docker::Error
5
+
6
+ attr_reader :url, :options
7
+
8
+ # Create a new Connection. By default, the Connection points to localhost at
9
+ # port 4243, but this can be changed via an options Hash.
10
+ def initialize(url = 'http://localhost', options = {})
11
+ unless options.is_a?(Hash)
12
+ raise Docker::Error::ArgumentError, "Expected a Hash, got: #{options}"
13
+ end
14
+ self.url = url
15
+ self.options = { :port => 4243 }.merge(options)
16
+ end
17
+
18
+ # The actual client that sends HTTP methods to the docker server.
19
+ def resource
20
+ @resource ||= Excon.new(self.url, self.options)
21
+ end
22
+
23
+ # Delegate all HTTP methods to the resource.
24
+ [:get, :put, :post, :delete, :request].each do |method|
25
+ define_method(method) do |*args, &block|
26
+ begin
27
+ self.resource.public_send(method, *args, &block)
28
+ rescue Excon::Errors::BadRequest => ex
29
+ raise ClientError, ex.message
30
+ rescue Excon::Errors::InternalServerError => ex
31
+ raise ServerError, ex.message
32
+ end
33
+ end
34
+ end
35
+
36
+ # Send a request to the server and then parse it into a Hash.
37
+ def json_request(method, path, query = {}, &block)
38
+ params = compile_request_params(method, path, query, &block)
39
+ body = self.request(params).body
40
+ JSON.parse(body) unless (body.nil? || body.empty? || (body == 'null'))
41
+ rescue JSON::ParserError => ex
42
+ raise UnexpectedResponseError, ex.message
43
+ end
44
+
45
+ def to_s
46
+ "Docker::Connection { :url => #{self.url}, :options => #{self.options} }"
47
+ end
48
+
49
+ private
50
+ attr_writer :url, :options
51
+
52
+ # Given an http_method, path, query, and optional block, returns the
53
+ # corresponding request parameters.
54
+ def compile_request_params(http_method, path, query, &block)
55
+ {
56
+ :method => http_method,
57
+ :path => path,
58
+ :query => query,
59
+ :headers => { 'Content-Type' => 'application/json' },
60
+ :expects => (200..204),
61
+ :idempotent => http_method == :get,
62
+ :response_block => block
63
+ }.reject { |_, v| v.nil? }
64
+ end
65
+ end
@@ -0,0 +1,54 @@
1
+ # This class represents a Docker Container. It's important to note that nothing
2
+ # is cached so that the information is always up to date.
3
+ class Docker::Container
4
+ include Docker::Model
5
+
6
+ resource_prefix '/containers'
7
+
8
+ create_request do |body|
9
+ response = self.connection.post(
10
+ :path => '/containers/create',
11
+ :headers => { 'Content-Type' => 'application/json' },
12
+ :body => body.to_json,
13
+ :expects => (200..204)
14
+ )
15
+ self.id = JSON.parse(response.body)['Id']
16
+ self
17
+ end
18
+
19
+ # Export the Container as a .tgz.
20
+ docker_request :export, :get
21
+ # Get more information about the Container.
22
+ docker_request :json, :get
23
+ # Wait for the current command to finish executing.
24
+ docker_request :wait, :post
25
+ # Start the Container.
26
+ docker_request :start, :post
27
+ # Inspect the Container's changes to the filesysetem
28
+ docker_request :changes, :get
29
+ # Stop the Container.
30
+ docker_request :stop, :post
31
+ # Kill the Container.
32
+ docker_request :kill, :post
33
+ # Restart the Container
34
+ docker_request :restart, :post
35
+
36
+ # Attach to a container's standard streams / logs.
37
+ def attach(options = {})
38
+ ensure_created!
39
+ self.connection.request(
40
+ :method => :post,
41
+ :path => "/containers/#{self.id}/attach",
42
+ :query => options,
43
+ :expects => (200..204)
44
+ ).body
45
+ end
46
+
47
+ # Create an Image from a Container's change.s
48
+ def commit(options = {})
49
+ ensure_created!
50
+ options.merge!('container' => self.id[0..7])
51
+ hash = self.connection.json_request(:post, '/commit', options)
52
+ Docker::Image.new(:id => hash['Id'], :connection => self.connection)
53
+ end
54
+ end