docker-api 1.8.0 → 1.8.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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/docker.rb +7 -1
- data/lib/docker/base.rb +24 -0
- data/lib/docker/container.rb +10 -25
- data/lib/docker/image.rb +16 -33
- data/lib/docker/version.rb +1 -1
- data/spec/docker/container_spec.rb +3 -1
- data/spec/docker/image_spec.rb +4 -4
- data/spec/docker_spec.rb +33 -0
- data/spec/vcr/Docker_Image/_tag/tags_the_image_with_the_repo_name.yml +6 -6
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e17294801992ba4c21ef2a8991aa45dac202d891
|
4
|
+
data.tar.gz: aa1b611592bec9e49568eb6f9c4e3bcf9cdeb8ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 656fe22d8ec340dc7044d76659d72b6853657613a3f2f74a9cca40c3468b7d7cb95e76c6e3103288efe98b9de90756246a2716fac00ceeb7b837d007a05fdc37
|
7
|
+
data.tar.gz: 501c1dd9fa9bcdf678ae605132d3db8ef2ae2e328a4f15309089bc51fe27d4ba72ea26802c3d6a7aba548c607024788e62a69784b00fa5897078da95052e9c32
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@ docker-api
|
|
2
2
|
==========
|
3
3
|
[](http://badge.fury.io/rb/docker-api) [](https://travis-ci.org/swipely/docker-api) [](https://codeclimate.com/github/swipely/docker-api) [](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
|
+
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
|
------------
|
data/lib/docker.rb
CHANGED
@@ -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
|
data/lib/docker/base.rb
ADDED
@@ -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
|
data/lib/docker/container.rb
CHANGED
@@ -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
|
65
|
+
Docker::Image.send(:new, self.connection, hash)
|
78
66
|
end
|
79
67
|
|
80
|
-
# Return a String
|
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
|
-
#
|
108
|
-
def
|
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
|
-
|
129
|
-
|
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
|
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
|
130
|
+
hashes.map { |hash| new(conn, hash) }
|
146
131
|
end
|
147
132
|
|
148
133
|
# Convenience method to return the path for a particular resource.
|
data/lib/docker/image.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
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
|
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
|
data/lib/docker/version.rb
CHANGED
@@ -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 {
|
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 }
|
data/spec/docker/image_spec.rb
CHANGED
@@ -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,
|
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
|
-
|
137
|
-
|
136
|
+
subject.tag(:repo => 'base2', :force => true)
|
137
|
+
subject.info['RepoTags'].should include('base2:latest')
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
data/spec/docker_spec.rb
CHANGED
@@ -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.
|
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
|
-
-
|
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:
|
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.
|
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
|
-
-
|
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:
|
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.
|
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-
|
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
|