docker-api 1.4.0 → 1.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
  SHA1:
3
- metadata.gz: cfc50f47e7b014bac994dd4077a3fd77abf38a3b
4
- data.tar.gz: 6ccc92a4b1be40bef5628a7800a4870e408e027e
3
+ metadata.gz: 649da0fe1cfd65917ce9975d649ba38846ce728c
4
+ data.tar.gz: 17a7e5506eccab710826b563b8fa74961f3d31ff
5
5
  SHA512:
6
- metadata.gz: 6bf902fd4852f9662dbf942f929be54a8d84416bd9ddbd4d2acbb822f5e3f7a7e6ec09ef73f14485598c5d90261256e362b32cdfa65734286b6356398b805a07
7
- data.tar.gz: 748c6151a34ce6aeae730af14e339bff538f3d637def12ebdc24db30e3185912cd61b37f4e73bfe95e9391ee31ac7fcdbacd82c6de25f40f8e6ee2e1a572747c
6
+ metadata.gz: 0884b950410fc3d3d8b169dbc6561efd26e08640cf9d5a0439e36ef743eb2decdb880378639b090da4f9e0a1380cf9fe5aef5829a9eb7b169112c33df893b6e6
7
+ data.tar.gz: 26c0b55692549c0f77f6a946967c228f5f86c005fdb555b2366dd1e015fcccab157b77fae1c31dc7a3ed2ab2346cba9295299b29fb617632ca16fa036f146015
data/README.md CHANGED
@@ -2,7 +2,7 @@ docker-api
2
2
  ==========
3
3
  [![Gem Version](https://badge.fury.io/rb/docker-api.png)](http://badge.fury.io/rb/docker-api) [![travis-ci](https://travis-ci.org/swipely/docker-api.png?branch=master)](https://travis-ci.org/swipely/docker-api) [![Code Climate](https://codeclimate.com/github/swipely/docker-api.png)](https://codeclimate.com/github/swipely/docker-api) [![Dependency Status](https://gemnasium.com/swipely/docker-api.png)](https://gemnasium.com/swipely/docker-api)
4
4
 
5
- This gem provides an object-oriented interface to the [Docker Remote API](http://docs.docker.io/en/latest/api/docker_remote_api_v1.4/). 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.5.1.
5
+ This gem provides an object-oriented interface to the [Docker Remote API](http://docs.docker.io/en/latest/api/docker_remote_api_v1.4/). 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.5.*.
6
6
 
7
7
  Installation
8
8
  ------------
@@ -74,7 +74,7 @@ require 'docker'
74
74
  # => true
75
75
 
76
76
  Docker.version
77
- # => { 'Version' => '0.4.0', 'GoVersion' => 'go1.0.3' }
77
+ # => { 'Version' => '0.5.2', 'GoVersion' => 'go1.1' }
78
78
 
79
79
  Docker.info
80
80
  # => { "Debug" => false, "Containers" => 187, "Images" => 196, "NFd" => 10, "NGoroutines" => 9, "MemoryLimit" => true }
@@ -160,19 +160,19 @@ container.json
160
160
 
161
161
  # Start running the Container.
162
162
  container.start
163
- # => nil
163
+ # => Docker::Container { :id => 492510dd38e4, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }
164
164
 
165
165
  # Stop running the Container.
166
166
  container.stop
167
- # => nil
167
+ # => Docker::Container { :id => 492510dd38e4, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }
168
168
 
169
169
  # Restart the Container.
170
170
  container.restart
171
- # => nil
171
+ # => Docker::Container { :id => 492510dd38e4, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }
172
172
 
173
173
  # Kill the command running in the Container.
174
174
  container.kill
175
- # => nil
175
+ # => Docker::Container { :id => 492510dd38e4, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }
176
176
 
177
177
  # Return the currently executing processes in a Container.
178
178
  container.top
data/lib/docker.rb CHANGED
@@ -8,8 +8,6 @@ require 'archive/tar/minitar'
8
8
  # The top-level module for this gem. It's purpose is to hold global
9
9
  # configuration variables that are used as defaults in other classes.
10
10
  module Docker
11
- extend self
12
-
13
11
  attr_reader :creds
14
12
 
15
13
  def url
@@ -64,12 +62,15 @@ module Docker
64
62
  rescue Docker::Error::DockerError
65
63
  raise Docker::Error::VersionError, "Expected API Version: #{API_VERSION}"
66
64
  end
65
+
66
+ module_function :url, :url=, :options, :options=, :connection,
67
+ :reset_connection!, :version, :info, :authenticate!,
68
+ :validate_version!
67
69
  end
68
70
 
69
71
  require 'docker/version'
70
72
  require 'docker/error'
71
73
  require 'docker/util'
72
74
  require 'docker/connection'
73
- require 'docker/model'
74
75
  require 'docker/container'
75
76
  require 'docker/image'
@@ -53,12 +53,13 @@ private
53
53
  query ||= {}
54
54
  opts ||= {}
55
55
  headers = opts.delete(:headers) || {}
56
+ content_type = opts[:body].nil? ? 'text/plain' : 'application/json'
56
57
  user_agent = "Swipely/Docker-API #{Docker::VERSION}"
57
58
  {
58
59
  :method => http_method,
59
60
  :path => "/v#{Docker::API_VERSION}#{path}",
60
61
  :query => query,
61
- :headers => { 'Content-Type' => 'text/plain',
62
+ :headers => { 'Content-Type' => content_type,
62
63
  'User-Agent' => user_agent,
63
64
  }.merge(headers),
64
65
  :expects => (200..204),
@@ -1,48 +1,32 @@
1
1
  # This class represents a Docker Container. It's important to note that nothing
2
2
  # is cached so that the information is always up to date.
3
3
  class Docker::Container
4
- include Docker::Model
5
4
  include Docker::Error
6
5
 
7
- set_resource_prefix '/containers'
6
+ attr_accessor :id, :connection
8
7
 
9
- set_create_request do |body|
10
- response = connection.post('/containers/create', nil, :body => body.to_json)
11
- @id = Docker::Util.parse_json(response)['Id']
12
- self
8
+ # The private new method accepts a connection and optional id.
9
+ def initialize(connection, id = nil)
10
+ if connection.is_a?(Docker::Connection)
11
+ @connection, @id = connection, id
12
+ else
13
+ raise ArgumentError, "Expected a Docker::Connection, got: #{connection}."
14
+ end
13
15
  end
14
16
 
15
- # Get more information about the Container.
16
- request :get, :json
17
- # Start the Container.
18
- request :post, :start
19
- # Inspect the Container's changes to the filesysetem
20
- request :get, :changes
21
- # Stop the Container.
22
- request :post, :stop
23
- # Kill the Container.
24
- request :post, :kill
25
- # Restart the Container
26
- request :post, :restart
27
-
28
17
  # Return a List of Hashes that represents the top running processes.
29
18
  def top(opts = {})
30
- resp = connection.get("/containers/#{id}/top", opts)
31
- hash = Docker::Util.parse_json(resp)
32
- hash['Processes'].map { |ary| Hash[hash['Titles'].zip(ary)] }
33
- end
34
-
35
- # For each method, `m`, define a method called `m?` that attempts the method,
36
- # but catches all Server errors.
37
- [:stop, :start, :kill, :restart].each do |method|
38
- define_method :"#{method}?" do |*args|
39
- begin; public_send(method, *args); rescue ServerError; end
19
+ resp = Docker::Util.parse_json(connection.get(path_for(:top), opts))
20
+ if resp['Processes'].nil?
21
+ []
22
+ else
23
+ resp['Processes'].map { |ary| Hash[resp['Titles'].zip(ary)] }
40
24
  end
41
25
  end
42
26
 
43
27
  # Wait for the current command to finish executing.
44
28
  def wait(time = 60)
45
- resp = connection.post("/containers/#{id}/wait", nil, :read_timeout => time)
29
+ resp = connection.post(path_for(:wait), nil, :read_timeout => time)
46
30
  Docker::Util.parse_json(resp)
47
31
  end
48
32
 
@@ -51,8 +35,8 @@ class Docker::Container
51
35
  # the command that is currently executing does not return a 0 status code, an
52
36
  # UnexpectedResponseError is raised.
53
37
  def run(cmd, time = 1000)
54
- if (code = tap(&:start?).wait(time)['StatusCode']).zero?
55
- commit.run(cmd).tap(&:start?)
38
+ if (code = tap(&:start).wait(time)['StatusCode']).zero?
39
+ commit.run(cmd).tap(&:start)
56
40
  else
57
41
  raise UnexpectedResponseError, "Command returned status code #{code}."
58
42
  end
@@ -60,21 +44,72 @@ class Docker::Container
60
44
 
61
45
  # Export the Container as a tar.
62
46
  def export(&block)
63
- connection.get("/containers/#{id}/export", nil, :response_block => block)
64
- true
47
+ connection.get(path_for(:export), {}, :response_block => block)
48
+ self
65
49
  end
66
50
 
67
51
  # Attach to a container's standard streams / logs.
68
52
  def attach(options = {}, &block)
69
- options = { :stream => true, :stdout => true }.merge(options)
70
- connection.post("/containers/#{id}/attach", options,
71
- :response_block => block)
53
+ opts = { :stream => true, :stdout => true }.merge(options)
54
+ connection.post(path_for(:attach), opts, :response_block => block)
72
55
  end
73
56
 
74
57
  # Create an Image from a Container's change.s
75
58
  def commit(options = {})
76
59
  options.merge!('container' => self.id[0..7])
77
60
  hash = Docker::Util.parse_json(connection.post('/commit', options))
78
- Docker::Image.send(:new, :id => hash['Id'], :connection => self.connection)
61
+ Docker::Image.send(:new, self.connection, hash['Id'])
62
+ end
63
+
64
+ # Return a String represntation of the Container.
65
+ def to_s
66
+ "Docker::Container { :id => #{self.id}, :connection => #{self.connection} }"
79
67
  end
68
+
69
+ # #json returns information about the Container, #changes returns a list of
70
+ # the changes the Container has made to the filesystem.
71
+ [:json, :changes].each do |method|
72
+ define_method(method) do |opts = {}|
73
+ Docker::Util.parse_json(connection.get(path_for(method), opts))
74
+ end
75
+ end
76
+
77
+ # #start!, #stop!, #kill!, and #restart! all perform the associated action and
78
+ # return the Container. #start, #stop, #kill, and #restart all do the same,
79
+ # but rescue from ServerErrors.
80
+ [:start, :stop, :kill, :restart].each do |method|
81
+ define_method(:"#{method}!") do |opts = {}|
82
+ connection.post(path_for(method), {}, :body => opts.to_json)
83
+ self
84
+ end
85
+
86
+ define_method(method) do |*args|
87
+ begin; public_send(:"#{method}!", *args); rescue ServerError; self end
88
+ end
89
+ end
90
+
91
+ # Create a new Container.
92
+ def self.create(opts = {}, conn = Docker.connection)
93
+ instance = new(conn)
94
+ resp = conn.post('/containers/create', {}, :body => opts.to_json)
95
+ if (instance.id = Docker::Util.parse_json(resp)['Id']).nil?
96
+ raise UnexpectedResponseError, 'Create response did not contain an Id'
97
+ else
98
+ instance
99
+ end
100
+ end
101
+
102
+ # Return all of the Containers.
103
+ def self.all(opts = {}, conn = Docker.connection)
104
+ hashes = Docker::Util.parse_json(conn.get('/containers/json', opts)) || []
105
+ hashes.map { |hash| new(conn, hash['Id']) }
106
+ end
107
+
108
+ # Convenience method to return the path for a particular resource.
109
+ def path_for(resource)
110
+ "/containers/#{self.id}/#{resource}"
111
+ end
112
+
113
+ private :path_for
114
+ private_class_method :new
80
115
  end
data/lib/docker/image.rb CHANGED
@@ -1,47 +1,45 @@
1
1
  # This class represents a Docker Image.
2
2
  class Docker::Image
3
- include Docker::Model
4
3
  include Docker::Error
5
4
 
6
- set_resource_prefix '/images'
5
+ attr_accessor :id, :connection
7
6
 
8
- set_create_request do |options|
9
- body = connection.post('/images/create', options)
10
- @id = Docker::Util.parse_json(body)['status'] rescue nil
11
- @id ||= options['fromImage']
12
- @id ||= "#{options['repo']}/#{options['tag']}"
13
- self
7
+ # The private new method accepts a connection and optional id.
8
+ def initialize(connection, id = nil)
9
+ if connection.is_a?(Docker::Connection)
10
+ @connection, @id = connection, id
11
+ else
12
+ raise ArgumentError, "Expected a Docker::Connection, got: #{connection}."
13
+ end
14
14
  end
15
15
 
16
- # Tag the Image.
17
- request :post, :tag
18
- # Get more information about the Image.
19
- request :get, :json
20
- # Get the history of the Image.
21
- request :get, :history
22
-
23
16
  # Given a command and optional list of streams to attach to, run a command on
24
17
  # an Image. This will not modify the Image, but rather create a new Container
25
18
  # to run the Image.
26
19
  def run(cmd)
27
20
  cmd = cmd.split(/\s+/) if cmd.is_a?(String)
28
21
  Docker::Container.create({ 'Image' => self.id, 'Cmd' => cmd }, connection)
29
- .tap(&:start)
22
+ .tap(&:start!)
30
23
  end
31
24
 
32
25
  # Push the Image to the Docker registry.
33
26
  def push(options = {})
34
- connection.post("/images/#{self.id}/push", options, :body => Docker.creds)
35
- true
27
+ connection.post(path_for(:push), options, :body => Docker.creds)
28
+ self
29
+ end
30
+
31
+ # Tag the Image.
32
+ def tag(opts = {})
33
+ Docker::Util.parse_json(connection.post(path_for(:tag), opts))
36
34
  end
37
35
 
38
36
  # Insert a file into the Image, returns a new Image that has that file.
39
37
  def insert(query = {})
40
- body = connection.post("/images/#{self.id}/insert", query)
38
+ body = connection.post(path_for(:insert), query)
41
39
  if (id = body.match(/{"Id":"([a-f0-9]+)"}\z/)).nil? || id[1].empty?
42
40
  raise UnexpectedResponseError, "Could not find Id in '#{body}'"
43
41
  else
44
- self.class.send(:new, :id => id[1], :connection => self.connection)
42
+ self.class.send(:new, connection, id[1])
45
43
  end
46
44
  end
47
45
 
@@ -50,15 +48,46 @@ class Docker::Image
50
48
  connection.delete("/images/#{self.id}")
51
49
  end
52
50
 
51
+ # Return a String representation of the Image.
52
+ def to_s
53
+ "Docker::Image { :id => #{self.id}, :connection => #{self.connection} }"
54
+ end
55
+
56
+ # #json returns extra information about an Image, #history returns its
57
+ # history.
58
+ [:json, :history].each do |method|
59
+ define_method(method) do |opts = {}|
60
+ Docker::Util.parse_json(connection.get(path_for(method), opts))
61
+ end
62
+ end
63
+
53
64
  class << self
54
65
  include Docker::Error
55
66
 
67
+ # Create a new Image.
68
+ def create(opts = {}, conn = Docker.connection)
69
+ instance = new(conn)
70
+ conn.post('/images/create', opts)
71
+ id = opts['repo'] ? "#{opts['repo']}/#{opts['tag']}" : opts['fromImage']
72
+ if (instance.id = id).nil?
73
+ raise UnexpectedResponseError, 'Create response did not contain an Id'
74
+ else
75
+ instance
76
+ end
77
+ end
78
+
79
+ # Return every Image.
80
+ def all(opts = {}, conn = Docker.connection)
81
+ hashes = Docker::Util.parse_json(conn.get('/images/json', opts)) || []
82
+ hashes.map { |hash| new(conn, hash['Id']) }
83
+ end
84
+
56
85
  # Given a query like `{ :term => 'sshd' }`, queries the Docker Registry for
57
- # a corresponiding Image.
86
+ # a corresponding Image.
58
87
  def search(query = {}, connection = Docker.connection)
59
88
  body = connection.get('/images/search', query)
60
89
  hashes = Docker::Util.parse_json(body) || []
61
- hashes.map { |hash| new(:id => hash['Name'], :connection => connection) }
90
+ hashes.map { |hash| new(connection, hash['Name']) }
62
91
  end
63
92
 
64
93
  # Import an Image from the output of Docker::Container#export.
@@ -67,17 +96,17 @@ class Docker::Image
67
96
  body = connection.post(
68
97
  '/images/create',
69
98
  options.merge('fromSrc' => '-'),
70
- :headers => { 'Transfer-Encoding' => 'chunked' }
99
+ :headers => { 'Content-Type' => 'application/tar',
100
+ 'Transfer-Encoding' => 'chunked' }
71
101
  ) { io.read(Excon.defaults[:chunk_size]).to_s }
72
- new(:id => Docker::Util.parse_json(body)['status'],
73
- :connection => connection)
102
+ new(connection, Docker::Util.parse_json(body)['status'])
74
103
  end
75
104
  end
76
105
 
77
106
  # Given a Dockerfile as a string, builds an Image.
78
107
  def build(commands, connection = Docker.connection)
79
108
  body = connection.post('/build', {}, :body => create_tar(commands))
80
- new(:id => extract_id(body), :connection => connection)
109
+ new(connection, extract_id(body))
81
110
  end
82
111
 
83
112
  # Given a directory that contains a Dockerfile, builds an Image.
@@ -88,7 +117,7 @@ class Docker::Image
88
117
  :headers => { 'Content-Type' => 'application/tar',
89
118
  'Transfer-Encoding' => 'chunked' }
90
119
  ) { tar.read(Excon.defaults[:chunk_size]).to_s }
91
- new(:id => extract_id(body), :connection => connection)
120
+ new(connection, extract_id(body))
92
121
  ensure
93
122
  tar.close unless tar.nil?
94
123
  end
@@ -121,4 +150,11 @@ class Docker::Image
121
150
  FileUtils.cd(cwd)
122
151
  end
123
152
  end
153
+
154
+ # Convenience method to return the path for a particular resource.
155
+ def path_for(resource)
156
+ "/images/#{self.id}/#{resource}"
157
+ end
158
+
159
+ private :path_for
124
160
  end
data/lib/docker/util.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # This module holds shared logic that doesn't really belong anywhere else in the
2
2
  # gem.
3
3
  module Docker::Util
4
- extend self
5
4
  include Docker::Error
6
5
 
7
6
  def parse_json(body)
@@ -9,4 +8,6 @@ module Docker::Util
9
8
  rescue JSON::ParserError => ex
10
9
  raise UnexpectedResponseError, ex.message
11
10
  end
11
+
12
+ module_function :parse_json
12
13
  end
@@ -1,6 +1,6 @@
1
1
  module Docker
2
2
  # The version of the docker-api gem.
3
- VERSION = '1.4.0'
3
+ VERSION = '1.5.0'
4
4
 
5
5
  # The version of the compatible Docker remote API.
6
6
  API_VERSION = '1.4'
@@ -4,7 +4,7 @@ require 'spec_helper'
4
4
  # Docker daemon and have the base Image pulled.
5
5
  describe Docker::Container do
6
6
  describe '#to_s' do
7
- subject { described_class.send(:new, :id => rand(10000).to_s) }
7
+ subject { described_class.send(:new, Docker.connection, rand(10000).to_s) }
8
8
 
9
9
  let(:id) { 'bf119e2' }
10
10
  let(:connection) { Docker.connection }
@@ -91,13 +91,20 @@ describe Docker::Container do
91
91
  end
92
92
 
93
93
  describe '#start' do
94
- subject { described_class.create('Cmd' => %w[true], 'Image' => 'base') }
94
+ subject {
95
+ described_class.create(
96
+ 'Cmd' => %w[test -d /foo],
97
+ 'Image' => 'base',
98
+ 'Volumes' => {'/foo' => {}}
99
+ )
100
+ }
101
+ let(:all) { Docker::Container.all }
102
+
103
+ before { subject.start('Binds' => ["/tmp:/foo"]) }
95
104
 
96
105
  it 'starts the container', :vcr do
97
- subject.start
98
- described_class.all.map(&:id).should be_any { |id|
99
- id.start_with?(subject.id)
100
- }
106
+ all.map(&:id).should be_any { |id| id.start_with?(subject.id) }
107
+ subject.wait(10)['StatusCode'].should be_zero
101
108
  end
102
109
  end
103
110
 
@@ -214,14 +221,7 @@ describe Docker::Container do
214
221
  describe '.create' do
215
222
  subject { described_class }
216
223
 
217
- context 'when the body is not a Hash' do
218
- it 'raises an error' do
219
- expect { subject.create(:not_a_hash) }
220
- .to raise_error(Docker::Error::ArgumentError)
221
- end
222
- end
223
-
224
- context 'when the Container does not yet exist and the body is a Hash' do
224
+ context 'when the Container does not yet exist' do
225
225
  context 'when the HTTP request does not return a 200' do
226
226
  before { Excon.stub({ :method => :post }, { :status => 400 }) }
227
227
  after { Excon.stubs.shift }
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Docker::Image do
4
4
  describe '#to_s' do
5
- subject { described_class.send(:new, :id => rand(10000).to_s) }
5
+ subject { described_class.send(:new, Docker.connection, id) }
6
6
 
7
7
  let(:id) { 'bf119e2' }
8
8
  let(:connection) { Docker.connection }
@@ -102,13 +102,6 @@ describe Docker::Image do
102
102
  describe '.create' do
103
103
  subject { described_class }
104
104
 
105
- context 'when the body is not a Hash' do
106
- it 'raises an error' do
107
- expect { subject.create(:not_a_hash) }
108
- .to raise_error(Docker::Error::ArgumentError)
109
- end
110
- end
111
-
112
105
  context 'when the Image does not yet exist and the body is a Hash' do
113
106
  let(:image) { subject.create('fromImage' => 'base') }
114
107
 
@@ -0,0 +1,30 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://localhost:4243/v1.4/containers/create
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"Hostname":"","User":"","Memory":0,"MemorySwap":0,"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":null,"Cmd":["date"],"Dns":null,"Image":"base","Volumes":{},"VolumesFrom":""}'
9
+ headers:
10
+ Content-Type:
11
+ - text/plain
12
+ User-Agent:
13
+ - Swipely/Docker-API 1.4.0
14
+ response:
15
+ status:
16
+ code: 201
17
+ message: ''
18
+ headers:
19
+ Content-Type:
20
+ - text/plain; charset=utf-8
21
+ Content-Length:
22
+ - '21'
23
+ Date:
24
+ - Thu, 08 Aug 2013 14:47:05 GMT
25
+ body:
26
+ encoding: UTF-8
27
+ string: '{"Id":"3e4587069eb0"}'
28
+ http_version:
29
+ recorded_at: Thu, 08 Aug 2013 14:47:05 GMT
30
+ recorded_with: VCR 2.4.0
@@ -5,55 +5,61 @@ http_interactions:
5
5
  uri: http://localhost:4243/v1.4/containers/create
6
6
  body:
7
7
  encoding: UTF-8
8
- string: '{"Cmd":["true"],"Image":"base"}'
8
+ string: ! '{"Cmd":["test","-d","/foo"],"Image":"base","Volumes":{"/foo":{}}}'
9
9
  headers:
10
10
  Content-Type:
11
11
  - text/plain
12
12
  User-Agent:
13
- - Swipely/Docker-API 1.3.1
13
+ - Swipely/Docker-API 1.4.0
14
14
  response:
15
15
  status:
16
16
  code: 201
17
17
  message: ''
18
18
  headers:
19
- Content-Type:
20
- - text/plain; charset=utf-8
21
- Content-Length:
22
- - '21'
23
- Date:
24
- - Wed, 07 Aug 2013 16:51:14 GMT
19
+ !binary "Q29udGVudC1UeXBl":
20
+ - !binary |-
21
+ dGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA==
22
+ !binary "Q29udGVudC1MZW5ndGg=":
23
+ - !binary |-
24
+ MjE=
25
+ !binary "RGF0ZQ==":
26
+ - !binary |-
27
+ RnJpLCAwOSBBdWcgMjAxMyAwODo1MDowNSBHTVQ=
25
28
  body:
26
- encoding: UTF-8
27
- string: '{"Id":"006a81e3a9ef"}'
29
+ encoding: US-ASCII
30
+ string: ! '{"Id":"3632688f5774"}'
28
31
  http_version:
29
- recorded_at: Wed, 07 Aug 2013 16:51:14 GMT
32
+ recorded_at: Fri, 09 Aug 2013 08:50:06 GMT
30
33
  - request:
31
34
  method: post
32
- uri: http://localhost:4243/v1.4/containers/006a81e3a9ef/start
35
+ uri: http://localhost:4243/v1.4/containers/3632688f5774/start
33
36
  body:
34
- encoding: US-ASCII
35
- string: ''
37
+ encoding: UTF-8
38
+ string: ! '{"Binds":["/tmp:/foo"]}'
36
39
  headers:
37
40
  Content-Type:
38
- - text/plain
41
+ - application/json
39
42
  User-Agent:
40
- - Swipely/Docker-API 1.3.1
43
+ - Swipely/Docker-API 1.4.0
41
44
  response:
42
45
  status:
43
46
  code: 204
44
47
  message: ''
45
48
  headers:
46
- Content-Type:
47
- - text/plain; charset=utf-8
48
- Content-Length:
49
- - '0'
50
- Date:
51
- - Wed, 07 Aug 2013 16:51:14 GMT
49
+ !binary "Q29udGVudC1UeXBl":
50
+ - !binary |-
51
+ dGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA==
52
+ !binary "Q29udGVudC1MZW5ndGg=":
53
+ - !binary |-
54
+ MA==
55
+ !binary "RGF0ZQ==":
56
+ - !binary |-
57
+ RnJpLCAwOSBBdWcgMjAxMyAwODo1MDowNiBHTVQ=
52
58
  body:
53
- encoding: UTF-8
59
+ encoding: US-ASCII
54
60
  string: ''
55
61
  http_version:
56
- recorded_at: Wed, 07 Aug 2013 16:51:14 GMT
62
+ recorded_at: Fri, 09 Aug 2013 08:50:06 GMT
57
63
  - request:
58
64
  method: get
59
65
  uri: http://localhost:4243/v1.4/containers/json
@@ -64,22 +70,84 @@ http_interactions:
64
70
  Content-Type:
65
71
  - text/plain
66
72
  User-Agent:
67
- - Swipely/Docker-API 1.3.1
73
+ - Swipely/Docker-API 1.4.0
68
74
  response:
69
75
  status:
70
76
  code: 200
71
77
  message: ''
78
+ headers:
79
+ !binary "Q29udGVudC1UeXBl":
80
+ - !binary |-
81
+ YXBwbGljYXRpb24vanNvbg==
82
+ !binary "Q29udGVudC1MZW5ndGg=":
83
+ - !binary |-
84
+ OTQ2
85
+ !binary "RGF0ZQ==":
86
+ - !binary |-
87
+ RnJpLCAwOSBBdWcgMjAxMyAwODo1MDowNiBHTVQ=
88
+ body:
89
+ encoding: US-ASCII
90
+ string: ! '[{"Id":"3632688f5774a1a5077e0b29e4410458ae43ec9dbaa400b10e68b385206e0cff","Image":"base:latest","Command":"test
91
+ -d /foo","Created":1376038205,"Status":"Up Less than a second","Ports":"","SizeRw":0,"SizeRootFs":0},{"Id":"965d1be64f580f590fa712f6e34b1186cd937f1448b6d5feeeb02174dd562cba","Image":"c401009f3872","Command":"/bin/bash
92
+ --login -c cd /app && bundle exec rackup -p $PORT","Created":1376001906,"Status":"Up
93
+ 10 hours","Ports":"","SizeRw":0,"SizeRootFs":0},{"Id":"371a31ee0515e231b53331827e2169a781d605259ca75f0d1b1593095fee6924","Image":"69e523818a5f","Command":"/bin/bash
94
+ --login -c cd /app && bundle exec rackup config.ru -p 80","Created":1375967943,"Status":"Up
95
+ 19 hours","Ports":"","SizeRw":0,"SizeRootFs":0},{"Id":"c7a4fe69a7249d6db5f24106891e1c28ee4bfe538ece09a53574c0b91850f165","Image":"samalba/hipache:latest","Command":"supervisord
96
+ -n","Created":1375657256,"Status":"Up 19 hours","Ports":"80-\u003e80","SizeRw":0,"SizeRootFs":0}]'
97
+ http_version:
98
+ recorded_at: Fri, 09 Aug 2013 08:50:06 GMT
99
+ - request:
100
+ method: post
101
+ uri: http://localhost:4243/v1.4/containers/3632688f5774/wait
102
+ body:
103
+ encoding: US-ASCII
104
+ string: ''
72
105
  headers:
73
106
  Content-Type:
74
- - application/json
75
- Content-Length:
76
- - '207'
77
- Date:
78
- - Wed, 07 Aug 2013 16:51:14 GMT
107
+ - text/plain
108
+ User-Agent:
109
+ - Swipely/Docker-API 1.4.0
110
+ response:
111
+ status:
112
+ code: 200
113
+ message: ''
114
+ headers:
115
+ !binary "Q29udGVudC1UeXBl":
116
+ - !binary |-
117
+ YXBwbGljYXRpb24vanNvbg==
118
+ !binary "Q29udGVudC1MZW5ndGg=":
119
+ - !binary |-
120
+ MTY=
121
+ !binary "RGF0ZQ==":
122
+ - !binary |-
123
+ RnJpLCAwOSBBdWcgMjAxMyAwODo1MDowNiBHTVQ=
79
124
  body:
80
- encoding: UTF-8
81
- string: '[{"Id":"006a81e3a9efb2d6b6b1bf7b25031f7c0ca972e731c4efeaaab30b75997d5804","Image":"base2:latest","Command":"true
82
- ","Created":1375894274,"Status":"Up Less than a second","Ports":"","SizeRw":0,"SizeRootFs":0}]'
125
+ encoding: US-ASCII
126
+ string: ! '{"StatusCode":0}'
127
+ http_version:
128
+ recorded_at: Fri, 09 Aug 2013 08:50:06 GMT
129
+ - request:
130
+ method: post
131
+ uri: http://localhost:4243/v1.4/containers/3632688f5774/attach?logs=true&stderr=true&stdout=true&stream=false
132
+ body:
133
+ encoding: US-ASCII
134
+ string: ''
135
+ headers:
136
+ Content-Type:
137
+ - text/plain
138
+ User-Agent:
139
+ - Swipely/Docker-API 1.4.0
140
+ response:
141
+ status:
142
+ code: 200
143
+ message: ''
144
+ headers:
145
+ !binary "Q29udGVudC1UeXBl":
146
+ - !binary |-
147
+ YXBwbGljYXRpb24vdm5kLmRvY2tlci5yYXctc3RyZWFt
148
+ body:
149
+ encoding: US-ASCII
150
+ string: ''
83
151
  http_version:
84
- recorded_at: Wed, 07 Aug 2013 16:51:14 GMT
85
- recorded_with: VCR 2.4.0
152
+ recorded_at: Fri, 09 Aug 2013 08:50:06 GMT
153
+ recorded_with: VCR 2.5.0
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docker-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Swipely, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-07 00:00:00.000000000 Z
11
+ date: 2013-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: excon
@@ -171,7 +171,6 @@ files:
171
171
  - lib/docker/container.rb
172
172
  - lib/docker/error.rb
173
173
  - lib/docker/image.rb
174
- - lib/docker/model.rb
175
174
  - lib/docker/util.rb
176
175
  - lib/docker/version.rb
177
176
  - spec/docker/connection_spec.rb
@@ -189,6 +188,7 @@ files:
189
188
  - spec/vcr/Docker_Container/_attach/yields_each_chunk.yml
190
189
  - spec/vcr/Docker_Container/_changes/returns_the_changes_as_an_array.yml
191
190
  - spec/vcr/Docker_Container/_commit/creates_a_new_Image_from_the_Container_s_changes.yml
191
+ - spec/vcr/Docker_Container/_create/when_the_Container_does_not_yet_exist/when_the_HTTP_request_returns_a_200/sets_the_id.yml
192
192
  - 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
193
193
  - spec/vcr/Docker_Container/_export/yields_each_chunk.yml
194
194
  - spec/vcr/Docker_Container/_json/returns_the_description_as_a_Hash.yml
@@ -254,6 +254,7 @@ test_files:
254
254
  - spec/vcr/Docker_Container/_attach/yields_each_chunk.yml
255
255
  - spec/vcr/Docker_Container/_changes/returns_the_changes_as_an_array.yml
256
256
  - spec/vcr/Docker_Container/_commit/creates_a_new_Image_from_the_Container_s_changes.yml
257
+ - spec/vcr/Docker_Container/_create/when_the_Container_does_not_yet_exist/when_the_HTTP_request_returns_a_200/sets_the_id.yml
257
258
  - 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
258
259
  - spec/vcr/Docker_Container/_export/yields_each_chunk.yml
259
260
  - spec/vcr/Docker_Container/_json/returns_the_description_as_a_Hash.yml
data/lib/docker/model.rb DELETED
@@ -1,77 +0,0 @@
1
- # This module is intended to be used as a Mixin for all objects exposed by the
2
- # Remote API. Currently, these are limited to Containers and Images.
3
- module Docker::Model
4
- include Docker::Error
5
-
6
- attr_reader :id, :connection
7
-
8
- def self.included(base)
9
- base.class_eval do
10
- extend ClassMethods
11
- private_class_method :new, :request, :set_create_request,
12
- :set_resource_prefix
13
- end
14
- end
15
-
16
- # Creates a new Model with the specified id and Connection. If a Connection
17
- # is specified and it is not a Docker::Connection, a
18
- # Docker::Error::ArgumentError is raised.
19
- def initialize(options = {})
20
- if (options[:connection] ||= Docker.connection).is_a?(Docker::Connection)
21
- @id, @connection = options[:id], options[:connection]
22
- else
23
- raise ArgumentError, 'Expected a Docker::Connection.'
24
- end
25
- end
26
-
27
- def to_s
28
- "#{self.class.name} { :id => #{id}, :connection => #{connection} }"
29
- end
30
-
31
- # This defines the DSL for the including Classes.
32
- module ClassMethods
33
- include Docker::Error
34
- attr_reader :resource_prefix, :create_request
35
-
36
- # Define the Model's prefix for all requests.
37
- def set_resource_prefix(val)
38
- @resource_prefix = val
39
- end
40
-
41
- # Define how the Model should send a create request to the server.
42
- def set_create_request(&block)
43
- @create_request = block
44
- end
45
-
46
- # Define a method named `action` that sends an http `method` request to the
47
- # Docker Server.
48
- def request(method, action, opts = {}, &outer_block)
49
- define_method(action) do |query = nil, &block|
50
- new_opts = {
51
- :path => "#{self.class.resource_prefix}/#{self.id}/#{action}",
52
- :json => true
53
- }.merge(opts)
54
- body = connection.request(method, new_opts[:path], query,
55
- new_opts[:excon], &block)
56
- body = Docker::Util.parse_json(body) if new_opts[:json]
57
- outer_block.nil? ? body : instance_exec(body, &outer_block)
58
- end
59
- end
60
-
61
- # Create a Model with the specified body. Raises a
62
- # Docker::Error::ArgumentError if the argument is not a Hash. Otherwise,
63
- # instances execs the Class's #create_request method with the single
64
- # argument.
65
- def create(opts = {}, conn = Docker.connection)
66
- raise Docker::Error::ArgumentError, 'Expected a Hash' if !opts.is_a?(Hash)
67
- new(:connection => conn).instance_exec(opts, &create_request)
68
- end
69
-
70
- # Retrieve every Instance of a model for the given server.
71
- def all(options = {}, connection = Docker.connection)
72
- path = "#{resource_prefix}/json"
73
- hashes = Docker::Util.parse_json(connection.get(path, options)) || []
74
- hashes.map { |hash| new(:id => hash['Id'], :connection => connection) }
75
- end
76
- end
77
- end