docker-api 1.8.0 → 1.8.1

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: dc5ba28fab5aed18ec66531e1b33aa0cbec86e12
4
- data.tar.gz: b860c92de1e24af1f431399b07ee529f7c1a73dc
3
+ metadata.gz: e17294801992ba4c21ef2a8991aa45dac202d891
4
+ data.tar.gz: aa1b611592bec9e49568eb6f9c4e3bcf9cdeb8ae
5
5
  SHA512:
6
- metadata.gz: 3ab3594b2951e5789078ea05081a9f9dfdc595cd8b2de06cab2ca75c877e0f5936184076de080d8ce6d7c3aada2ce1a7244b0f76ae0042cff8997fdcce26836d
7
- data.tar.gz: a239960f224a37afc14432b7e450dd26b374e3dea52d25b83fa161f204491efc40375f7343b3701f52eaff6356120f3c5a3815e3d1ba119df5c29188ec38b4af
6
+ metadata.gz: 656fe22d8ec340dc7044d76659d72b6853657613a3f2f74a9cca40c3468b7d7cb95e76c6e3103288efe98b9de90756246a2716fac00ceeb7b837d007a05fdc37
7
+ data.tar.gz: 501c1dd9fa9bcdf678ae605132d3db8ef2ae2e328a4f15309089bc51fe27d4ba72ea26802c3d6a7aba548c607024788e62a69784b00fa5897078da95052e9c32
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.6.*.
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.8.*.
6
6
 
7
7
  Installation
8
8
  ------------
@@ -20,6 +20,7 @@ module Docker
20
20
  autoload :Image, 'docker/image'
21
21
  autoload :Messages, 'docker/messages'
22
22
  autoload :Util, 'docker/util'
23
+ autoload :Base, 'docker/base'
23
24
 
24
25
  def default_socket_url
25
26
  'unix:///var/run/docker.sock'
@@ -30,7 +31,12 @@ module Docker
30
31
  end
31
32
 
32
33
  def url
33
- @url ||= ENV['DOCKER_URL'] || default_socket_url
34
+ @url ||= ENV['DOCKER_URL'] || ENV['DOCKER_HOST'] || default_socket_url
35
+ # docker uses a default notation tcp:// which means tcp://localhost:4243
36
+ if @url == 'tcp://'
37
+ @url = 'tcp://localhost:4243'
38
+ end
39
+ @url
34
40
  end
35
41
 
36
42
  def options
@@ -0,0 +1,24 @@
1
+ # This class is a base class for Docker Container and Image.
2
+ # It is implementing accessor methods for the models attributes.
3
+ class Docker::Base
4
+ include Docker::Error
5
+
6
+ attr_accessor :connection, :info
7
+ attr_reader :id
8
+
9
+ # The private new method accepts a connection and optional id.
10
+ def initialize(connection, hash={})
11
+ unless connection.is_a?(Docker::Connection)
12
+ raise ArgumentError, "Expected a Docker::Connection, got: #{connection}."
13
+ end
14
+ normalize_hash(hash)
15
+ @connection, @info, @id = connection, hash, hash['id']
16
+ raise ArgumentError, "Must have id, got: #{hash}" unless @id
17
+ end
18
+
19
+ # The docker-api will some time return "ID" other times it will return "Id"
20
+ # and other times it will return "id". This method normalize it to "id"
21
+ def normalize_hash(hash)
22
+ hash["id"] ||= hash.delete("ID") || hash.delete("Id")
23
+ end
24
+ end
@@ -1,18 +1,6 @@
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
- class Docker::Container
4
- include Docker::Error
5
-
6
- attr_accessor :id, :connection
7
-
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
15
- end
3
+ class Docker::Container < Docker::Base
16
4
 
17
5
  # Return a List of Hashes that represents the top running processes.
18
6
  def top(opts = {})
@@ -74,10 +62,10 @@ class Docker::Container
74
62
  hash = Docker::Util.parse_json(connection.post('/commit',
75
63
  options,
76
64
  :body => config.to_json))
77
- Docker::Image.send(:new, self.connection, hash['Id'])
65
+ Docker::Image.send(:new, self.connection, hash)
78
66
  end
79
67
 
80
- # Return a String represntation of the Container.
68
+ # Return a String representation of the Container.
81
69
  def to_s
82
70
  "Docker::Container { :id => #{self.id}, :connection => #{self.connection} }"
83
71
  end
@@ -104,11 +92,12 @@ class Docker::Container
104
92
  end
105
93
  end
106
94
 
107
- # delete container
108
- def delete(options = {})
95
+ # remove container
96
+ def remove(options = {})
109
97
  connection.delete("/containers/#{self.id}", options)
110
98
  nil
111
99
  end
100
+ alias_method :delete, :remove
112
101
 
113
102
  def copy(path, &block)
114
103
  connection.post(path_for(:copy), {},
@@ -120,29 +109,25 @@ class Docker::Container
120
109
 
121
110
  # Create a new Container.
122
111
  def self.create(opts = {}, conn = Docker.connection)
123
- instance = new(conn)
124
112
  name = opts.delete('name')
125
113
  query = {}
126
114
  query['name'] = name if name
127
115
  resp = conn.post('/containers/create', query, :body => opts.to_json)
128
- if (instance.id = Docker::Util.parse_json(resp)['Id']).nil?
129
- raise UnexpectedResponseError, 'Create response did not contain an Id'
130
- else
131
- instance
132
- end
116
+ hash = Docker::Util.parse_json(resp) || {}
117
+ new(conn, hash)
133
118
  end
134
119
 
135
120
  # Return the container with specified ID
136
121
  def self.get(id, opts = {}, conn = Docker.connection)
137
122
  container_json = conn.get("/containers/#{URI.encode(id)}/json", opts)
138
123
  hash = Docker::Util.parse_json(container_json) || {}
139
- new(conn, hash['ID'])
124
+ new(conn, hash)
140
125
  end
141
126
 
142
127
  # Return all of the Containers.
143
128
  def self.all(opts = {}, conn = Docker.connection)
144
129
  hashes = Docker::Util.parse_json(conn.get('/containers/json', opts)) || []
145
- hashes.map { |hash| new(conn, hash['Id']) }
130
+ hashes.map { |hash| new(conn, hash) }
146
131
  end
147
132
 
148
133
  # Convenience method to return the path for a particular resource.
@@ -1,17 +1,5 @@
1
1
  # This class represents a Docker Image.
2
- class Docker::Image
3
- include Docker::Error
4
-
5
- attr_accessor :id, :connection, :info
6
-
7
- # The private new method accepts a connection and optional id.
8
- def initialize(connection, id = nil, info = {})
9
- if connection.is_a?(Docker::Connection)
10
- @connection, @id, @info = connection, id, info
11
- else
12
- raise ArgumentError, "Expected a Docker::Connection, got: #{connection}."
13
- end
14
- end
2
+ class Docker::Image < Docker::Base
15
3
 
16
4
  # Given a command and optional list of streams to attach to, run a command on
17
5
  # an Image. This will not modify the Image, but rather create a new Container
@@ -36,10 +24,7 @@ class Docker::Image
36
24
  def push(creds = nil, options = {})
37
25
  repository = self.info['RepoTags'].first.split(/:/)[0] rescue nil
38
26
 
39
- unless repository
40
- raise ArgumentError
41
- "Image does not have a name to push, got: #{repository}."
42
- end
27
+ raise ArgumentError, "Image does not have a name to push." unless repository
43
28
 
44
29
  credentials = creds || Docker.creds
45
30
  headers = Docker::Util.build_auth_header(credentials)
@@ -53,7 +38,10 @@ class Docker::Image
53
38
 
54
39
  # Tag the Image.
55
40
  def tag(opts = {})
56
- Docker::Util.parse_json(connection.post(path_for(:tag), opts))
41
+ self.info['RepoTags'] ||= []
42
+ connection.post(path_for(:tag), opts)
43
+ repo = opts['repo'] || opts[:repo]
44
+ self.info['RepoTags'] << (repo.include?(?:) ? repo : "#{repo}:latest")
57
45
  end
58
46
 
59
47
  # Insert a file into the Image, returns a new Image that has that file.
@@ -62,7 +50,7 @@ class Docker::Image
62
50
  if (id = body.match(/{"status":"([a-f0-9]+)"}\z/)).nil? || id[1].empty?
63
51
  raise UnexpectedResponseError, "Could not find Id in '#{body}'"
64
52
  else
65
- self.class.send(:new, connection, id[1])
53
+ self.class.send(:new, connection, 'id' => id[1])
66
54
  end
67
55
  end
68
56
 
@@ -80,13 +68,14 @@ class Docker::Image
80
68
 
81
69
  tar = Docker::Util.create_tar(file_hash)
82
70
  body = connection.post('/build', opts, :body => tar)
83
- self.class.send(:new, connection, Docker::Util.extract_id(body))
71
+ self.class.send(:new, connection, 'id' => Docker::Util.extract_id(body))
84
72
  end
85
73
 
86
74
  # Remove the Image from the server.
87
75
  def remove
88
76
  connection.delete("/images/#{self.id}")
89
77
  end
78
+ alias_method :delete, :remove
90
79
 
91
80
  # Return a String representation of the Image.
92
81
  def to_s
@@ -103,7 +92,6 @@ class Docker::Image
103
92
  end
104
93
 
105
94
  class << self
106
- include Docker::Error
107
95
 
108
96
  # Create a new Image.
109
97
  def create(opts = {}, creds = nil, conn = Docker.connection)
@@ -113,27 +101,22 @@ class Docker::Image
113
101
  else
114
102
  {}
115
103
  end
116
- instance = new(conn, {}, :headers => headers)
117
104
  conn.post('/images/create', opts)
118
105
  id = opts['repo'] ? "#{opts['repo']}/#{opts['tag']}" : opts['fromImage']
119
- if (instance.id = id).nil?
120
- raise UnexpectedResponseError, 'Create response did not contain an Id'
121
- else
122
- instance
123
- end
106
+ new(conn, 'id' => id, :headers => headers)
124
107
  end
125
108
 
126
109
  # Return a specific image.
127
110
  def get(id, opts = {}, conn = Docker.connection)
128
111
  image_json = conn.get("/images/#{URI.encode(id)}/json", opts)
129
112
  hash = Docker::Util.parse_json(image_json) || {}
130
- new(conn, hash['id'])
113
+ new(conn, hash)
131
114
  end
132
115
 
133
116
  # Return every Image.
134
117
  def all(opts = {}, conn = Docker.connection)
135
118
  hashes = Docker::Util.parse_json(conn.get('/images/json', opts)) || []
136
- hashes.map { |hash| new(conn, hash['Id'], hash.tap{|h| h.delete('Id')}) }
119
+ hashes.map { |hash| new(conn, hash) }
137
120
  end
138
121
 
139
122
  # Given a query like `{ :term => 'sshd' }`, queries the Docker Registry for
@@ -141,7 +124,7 @@ class Docker::Image
141
124
  def search(query = {}, connection = Docker.connection)
142
125
  body = connection.get('/images/search', query)
143
126
  hashes = Docker::Util.parse_json(body) || []
144
- hashes.map { |hash| new(connection, hash['name']) }
127
+ hashes.map { |hash| new(connection, 'id' => hash['name']) }
145
128
  end
146
129
 
147
130
  # Import an Image from the output of Docker::Container#export.
@@ -153,7 +136,7 @@ class Docker::Image
153
136
  :headers => { 'Content-Type' => 'application/tar',
154
137
  'Transfer-Encoding' => 'chunked' }
155
138
  ) { io.read(Excon.defaults[:chunk_size]).to_s }
156
- new(connection, Docker::Util.parse_json(body)['status'])
139
+ new(connection, 'id'=> Docker::Util.parse_json(body)['status'])
157
140
  end
158
141
  end
159
142
 
@@ -165,7 +148,7 @@ class Docker::Image
165
148
  :body => Docker::Util.create_tar('Dockerfile' => commands),
166
149
  :response_block => response_block_for_build(body, &block)
167
150
  )
168
- new(connection, Docker::Util.extract_id(body))
151
+ new(connection, 'id' => Docker::Util.extract_id(body))
169
152
  rescue Docker::Error::ServerError
170
153
  raise Docker::Error::UnexpectedResponseError
171
154
  end
@@ -185,7 +168,7 @@ class Docker::Image
185
168
  'Transfer-Encoding' => 'chunked' },
186
169
  :response_block => response_block_for_build(body, &block)
187
170
  ) { tar.read(Excon.defaults[:chunk_size]).to_s }
188
- new(connection, Docker::Util.extract_id(body))
171
+ new(connection, 'id' => Docker::Util.extract_id(body))
189
172
  ensure
190
173
  tar.close unless tar.nil?
191
174
  end
@@ -1,6 +1,6 @@
1
1
  module Docker
2
2
  # The version of the docker-api gem.
3
- VERSION = '1.8.0'
3
+ VERSION = '1.8.1'
4
4
 
5
5
  # The version of the compatible Docker remote API.
6
6
  API_VERSION = '1.8'
@@ -4,7 +4,9 @@ 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, Docker.connection, rand(10000).to_s) }
7
+ subject {
8
+ described_class.send(:new, Docker.connection, 'id' => rand(10000).to_s)
9
+ }
8
10
 
9
11
  let(:id) { 'bf119e2' }
10
12
  let(:connection) { Docker.connection }
@@ -2,13 +2,13 @@ require 'spec_helper'
2
2
 
3
3
  describe Docker::Image do
4
4
  describe '#to_s' do
5
- subject { described_class.new(Docker.connection, id, info) }
5
+ subject { described_class.new(Docker.connection, info) }
6
6
 
7
7
  let(:id) { 'bf119e2' }
8
8
  let(:connection) { Docker.connection }
9
9
 
10
10
  let(:info) do
11
- {"Repository" => "base", "Tag" => "latest",
11
+ {"id" => "bf119e2", "Repository" => "base", "Tag" => "latest",
12
12
  "Created" => 1364102658, "Size" => 24653, "VirtualSize" => 180116135}
13
13
  end
14
14
 
@@ -133,8 +133,8 @@ describe Docker::Image do
133
133
  subject { described_class.create('fromImage' => 'base') }
134
134
 
135
135
  it 'tags the image with the repo name', :vcr do
136
- expect { subject.tag(:repo => 'base2', :force => true) }
137
- .to_not raise_error
136
+ subject.tag(:repo => 'base2', :force => true)
137
+ subject.info['RepoTags'].should include('base2:latest')
138
138
  end
139
139
  end
140
140
 
@@ -5,6 +5,7 @@ describe Docker do
5
5
 
6
6
  before do
7
7
  ENV['DOCKER_URL'] = nil
8
+ ENV['DOCKER_HOST'] = nil
8
9
  end
9
10
 
10
11
  it { should be_a Module }
@@ -30,6 +31,38 @@ describe Docker do
30
31
  its(:url) { should == 'unixs:///var/run/not-docker.sock' }
31
32
  its(:connection) { should be_a Docker::Connection }
32
33
  end
34
+
35
+ context "when the DOCKER_HOST is set and uses default tcp://" do
36
+ before do
37
+ ENV['DOCKER_HOST'] = 'tcp://'
38
+ end
39
+
40
+ its(:options) { {} }
41
+ its(:url) { should == 'tcp://localhost:4243' }
42
+ its(:connection) { should be_a Docker::Connection }
43
+ end
44
+
45
+ context "when the DOCKER_HOST ENV variables is set" do
46
+ before do
47
+ ENV['DOCKER_HOST'] = 'tcp://someserver:8103'
48
+ end
49
+
50
+ its(:options) { {} }
51
+ its(:url) { should == 'tcp://someserver:8103' }
52
+ its(:connection) { should be_a Docker::Connection }
53
+ end
54
+
55
+ context "DOCKER_URL should take precedence over DOCKER_HOST" do
56
+ before do
57
+ ENV['DOCKER_HOST'] = 'tcp://someserver:8103'
58
+ ENV['DOCKER_URL'] = 'tcp://someotherserver:8103'
59
+
60
+ end
61
+
62
+ its(:options) { {} }
63
+ its(:url) { should == 'tcp://someotherserver:8103' }
64
+ its(:connection) { should be_a Docker::Connection }
65
+ end
33
66
  end
34
67
 
35
68
  describe '#reset_connection!' do
@@ -8,7 +8,7 @@ http_interactions:
8
8
  string: ''
9
9
  headers:
10
10
  User-Agent:
11
- - Swipely/Docker-API 1.7.6
11
+ - Swipely/Docker-API 1.8.0
12
12
  Content-Type:
13
13
  - text/plain
14
14
  response:
@@ -19,7 +19,7 @@ http_interactions:
19
19
  Content-Type:
20
20
  - application/json
21
21
  Date:
22
- - Wed, 12 Feb 2014 17:06:20 GMT
22
+ - Mon, 17 Feb 2014 19:21:58 GMT
23
23
  Connection:
24
24
  - close
25
25
  Transfer-Encoding:
@@ -34,7 +34,7 @@ http_interactions:
34
34
  complete\",\"progressDetail\":{},\"id\":\"b750fe79269d\"}{\"status\":\"Download
35
35
  complete\",\"progressDetail\":{},\"id\":\"b750fe79269d\"}"
36
36
  http_version:
37
- recorded_at: Wed, 12 Feb 2014 17:06:21 GMT
37
+ recorded_at: Mon, 17 Feb 2014 19:22:00 GMT
38
38
  - request:
39
39
  method: post
40
40
  uri: unix:///var/run/docker.sock/v1.8/images/base/tag?force=true&repo=base2
@@ -43,7 +43,7 @@ http_interactions:
43
43
  string: ''
44
44
  headers:
45
45
  User-Agent:
46
- - Swipely/Docker-API 1.7.6
46
+ - Swipely/Docker-API 1.8.0
47
47
  Content-Type:
48
48
  - text/plain
49
49
  response:
@@ -52,7 +52,7 @@ http_interactions:
52
52
  message:
53
53
  headers:
54
54
  Date:
55
- - Wed, 12 Feb 2014 17:06:21 GMT
55
+ - Mon, 17 Feb 2014 19:22:00 GMT
56
56
  Content-Length:
57
57
  - '0'
58
58
  Content-Type:
@@ -63,5 +63,5 @@ http_interactions:
63
63
  encoding: UTF-8
64
64
  string: ''
65
65
  http_version:
66
- recorded_at: Wed, 12 Feb 2014 17:06:21 GMT
66
+ recorded_at: Mon, 17 Feb 2014 19:22:00 GMT
67
67
  recorded_with: VCR 2.8.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.8.0
4
+ version: 1.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Swipely, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-12 00:00:00.000000000 Z
11
+ date: 2014-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: excon
@@ -154,6 +154,7 @@ files:
154
154
  - Rakefile
155
155
  - docker-api.gemspec
156
156
  - lib/docker.rb
157
+ - lib/docker/base.rb
157
158
  - lib/docker/connection.rb
158
159
  - lib/docker/container.rb
159
160
  - lib/docker/error.rb