docker-api 1.34.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +8 -12
- data/lib/docker/connection.rb +81 -16
- data/lib/docker/container.rb +3 -13
- data/lib/docker/event.rb +3 -1
- data/lib/docker/exec.rb +7 -0
- data/lib/docker/image.rb +22 -4
- data/lib/docker/network.rb +3 -3
- data/lib/docker/util.rb +47 -17
- data/lib/docker/version.rb +1 -4
- data/lib/docker.rb +14 -15
- data/lib/excon/middlewares/hijack.rb +4 -2
- metadata +6 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8bcdc6793c2627d187d2844a679965abf7903c58b89dc26de88f411feb8d0fd6
|
4
|
+
data.tar.gz: 3cc8a8aadeee74ab3ba28b25d147b795dae8aff22e53923a2911f36f7bbc3d5d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6fb00d23f25120f8341002958a9abedbff05bc27e11d5992308063569a640b9e51c3a492a0fdd00dae15e8f6ddbb62bc8c706b8fbe25d6a7c79719178194b328
|
7
|
+
data.tar.gz: f8fee2e81864164601e6cccd2e3cd3235df383217a2fd0c362a06a9da8448f0ef452306fa6a2d370c02ea95dbe9b9db1669d1ab39cdd4d1b880265fd0e57752d
|
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
docker-api
|
2
2
|
==========
|
3
|
-
[![Gem Version](https://badge.fury.io/rb/docker-api.svg)](https://badge.fury.io/rb/docker-api) [![
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/docker-api.svg)](https://badge.fury.io/rb/docker-api) [![Code Climate](https://codeclimate.com/github/upserve/docker-api.svg)](https://codeclimate.com/github/upserve/docker-api)
|
4
4
|
|
5
|
-
This gem provides an object-oriented interface to the [Docker
|
5
|
+
This gem provides an object-oriented interface to the [Docker Engine API](https://docs.docker.com/develop/sdk/). Every method listed there is implemented. At the time of this writing, docker-api is meant to interface with Docker version 1.4.*
|
6
6
|
|
7
|
-
If you're interested in using Docker to package your apps, we recommend the [dockly](https://github.com/
|
7
|
+
If you're interested in using Docker to package your apps, we recommend the [dockly](https://github.com/upserve/dockly) gem. Dockly provides a simple DSL for describing Docker containers that install as Debian packages and are controlled by upstart scripts.
|
8
8
|
|
9
9
|
Installation
|
10
10
|
------------
|
@@ -34,9 +34,11 @@ Usage
|
|
34
34
|
|
35
35
|
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 external method represents an API call.
|
36
36
|
|
37
|
+
At this time, basic `podman` support has been added via the podman docker-compatible API socket.
|
38
|
+
|
37
39
|
## Starting up
|
38
40
|
|
39
|
-
Follow the [installation instructions](https://docs.docker.com/
|
41
|
+
Follow the [installation instructions](https://docs.docker.com/install/), and then run:
|
40
42
|
|
41
43
|
```shell
|
42
44
|
$ sudo docker -d
|
@@ -52,7 +54,7 @@ If you're running Docker locally as a socket, there is no setup to do in Ruby. I
|
|
52
54
|
Docker.url = 'tcp://example.com:5422'
|
53
55
|
```
|
54
56
|
|
55
|
-
Two things to note here. The first is that this gem uses [excon](
|
57
|
+
Two things to note here. The first is that this gem uses [excon](https://github.com/excon/excon), so any of the options that are valid for `Excon.new` are also valid for `Docker.options`. Second, by default Docker runs on a socket. The gem will assume you want to connect to the socket unless you specify otherwise.
|
56
58
|
|
57
59
|
Also, you may set the above variables via `ENV` variables. For example:
|
58
60
|
|
@@ -76,8 +78,6 @@ irb(main):004:0> Docker.options
|
|
76
78
|
=> {}
|
77
79
|
```
|
78
80
|
|
79
|
-
Before doing anything else, ensure you have the correct version of the Docker API. To do this, run `Docker.validate_version!`. If your installed version is not supported, a `Docker::Error::VersionError` is raised.
|
80
|
-
|
81
81
|
### SSL
|
82
82
|
|
83
83
|
When running docker using SSL, setting the DOCKER_CERT_PATH will configure docker-api to use SSL.
|
@@ -413,7 +413,7 @@ container.read_file("/test")
|
|
413
413
|
|
414
414
|
# Export a Container. Since an export is typically at least 300M, chunks of the
|
415
415
|
# export are yielded instead of just returning the whole thing.
|
416
|
-
File.open('export.tar', 'w') do |
|
416
|
+
File.open('export.tar', 'w') do |file|
|
417
417
|
container.export { |chunk| file.write(chunk) }
|
418
418
|
end
|
419
419
|
# => nil
|
@@ -622,10 +622,6 @@ image 'repo:new_tag' => 'repo:tag' do
|
|
622
622
|
end
|
623
623
|
```
|
624
624
|
|
625
|
-
## Known issues
|
626
|
-
|
627
|
-
* If the docker daemon is always responding to your requests with a 400 Bad Request when using UNIX sockets, verify you're running Excon version 0.46.0 or greater. [Link](https://github.com/swipely/docker-api/issues/381)
|
628
|
-
|
629
625
|
## Not supported (yet)
|
630
626
|
|
631
627
|
* Generating a tarball of images and metadata for a repository specified by a name: https://docs.docker.com/engine/reference/api/docker_remote_api_v1.14/#get-a-tarball-containing-all-images-and-tags-in-a-repository
|
data/lib/docker/connection.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# This class represents a Connection to a Docker server. The Connection is
|
2
2
|
# immutable in that once the url and options is set they cannot be changed.
|
3
3
|
class Docker::Connection
|
4
|
+
require 'docker/util'
|
5
|
+
require 'docker/error'
|
6
|
+
|
4
7
|
include Docker::Error
|
5
8
|
|
6
9
|
attr_reader :url, :options
|
@@ -35,21 +38,58 @@ class Docker::Connection
|
|
35
38
|
|
36
39
|
# Send a request to the server with the `
|
37
40
|
def request(*args, &block)
|
41
|
+
retries ||= 0
|
38
42
|
request = compile_request_params(*args, &block)
|
39
43
|
log_request(request)
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
44
|
+
begin
|
45
|
+
resource.request(request).body
|
46
|
+
rescue Excon::Errors::BadRequest => ex
|
47
|
+
if retries < 2
|
48
|
+
response_cause = ''
|
49
|
+
begin
|
50
|
+
response_cause = JSON.parse(ex.response.body)['cause']
|
51
|
+
rescue JSON::ParserError
|
52
|
+
#noop
|
53
|
+
end
|
54
|
+
|
55
|
+
if response_cause.is_a?(String)
|
56
|
+
# The error message will tell the application type given and then the
|
57
|
+
# application type that the message should be
|
58
|
+
#
|
59
|
+
# This is not perfect since it relies on processing a message that
|
60
|
+
# could change in the future. However, it should be a good stop-gap
|
61
|
+
# until all methods are updated to pass in the appropriate content
|
62
|
+
# type.
|
63
|
+
#
|
64
|
+
# A current example message is:
|
65
|
+
# * 'Content-Type: application/json is not supported. Should be "application/x-tar"'
|
66
|
+
matches = response_cause.delete('"\'').scan(%r{(application/\S+)})
|
67
|
+
unless matches.count < 2
|
68
|
+
Docker.logger.warn(
|
69
|
+
<<~RETRY_WARNING
|
70
|
+
Automatically retrying with content type '#{response_cause}'
|
71
|
+
Original Error: #{ex}
|
72
|
+
RETRY_WARNING
|
73
|
+
) if Docker.logger
|
74
|
+
|
75
|
+
request[:headers]['Content-Type'] = matches.last.first
|
76
|
+
retries += 1
|
77
|
+
retry
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
raise ClientError, ex.response.body
|
82
|
+
rescue Excon::Errors::Unauthorized => ex
|
83
|
+
raise UnauthorizedError, ex.response.body
|
84
|
+
rescue Excon::Errors::NotFound => ex
|
85
|
+
raise NotFoundError, ex.response.body
|
86
|
+
rescue Excon::Errors::Conflict => ex
|
87
|
+
raise ConflictError, ex.response.body
|
88
|
+
rescue Excon::Errors::InternalServerError => ex
|
89
|
+
raise ServerError, ex.response.body
|
90
|
+
rescue Excon::Errors::Timeout => ex
|
91
|
+
raise TimeoutError, ex.message
|
92
|
+
end
|
53
93
|
end
|
54
94
|
|
55
95
|
def log_request(request)
|
@@ -60,13 +100,38 @@ class Docker::Connection
|
|
60
100
|
end
|
61
101
|
end
|
62
102
|
|
103
|
+
def to_s
|
104
|
+
"Docker::Connection { :url => #{url}, :options => #{options} }"
|
105
|
+
end
|
106
|
+
|
63
107
|
# Delegate all HTTP methods to the #request.
|
64
108
|
[:get, :put, :post, :delete].each do |method|
|
65
109
|
define_method(method) { |*args, &block| request(method, *args, &block) }
|
66
110
|
end
|
67
111
|
|
68
|
-
|
69
|
-
|
112
|
+
# Common attribute requests
|
113
|
+
def info
|
114
|
+
Docker::Util.parse_json(get('/info'))
|
115
|
+
end
|
116
|
+
|
117
|
+
def ping
|
118
|
+
get('/_ping')
|
119
|
+
end
|
120
|
+
|
121
|
+
def podman?
|
122
|
+
@podman ||= !(
|
123
|
+
Array(version['Components']).find do |component|
|
124
|
+
component['Name'].include?('Podman')
|
125
|
+
end
|
126
|
+
).nil?
|
127
|
+
end
|
128
|
+
|
129
|
+
def rootless?
|
130
|
+
@rootless ||= (info['Rootless'] == true)
|
131
|
+
end
|
132
|
+
|
133
|
+
def version
|
134
|
+
@version ||= Docker::Util.parse_json(get('/version'))
|
70
135
|
end
|
71
136
|
|
72
137
|
private
|
@@ -80,7 +145,7 @@ private
|
|
80
145
|
user_agent = "Swipely/Docker-API #{Docker::VERSION}"
|
81
146
|
{
|
82
147
|
:method => http_method,
|
83
|
-
:path =>
|
148
|
+
:path => path,
|
84
149
|
:query => query,
|
85
150
|
:headers => { 'Content-Type' => content_type,
|
86
151
|
'User-Agent' => user_agent,
|
data/lib/docker/container.rb
CHANGED
@@ -189,10 +189,10 @@ class Docker::Container
|
|
189
189
|
end
|
190
190
|
|
191
191
|
def streaming_logs(opts = {}, &block)
|
192
|
-
stack_size = opts.delete('stack_size') || -1
|
192
|
+
stack_size = opts.delete('stack_size') || opts.delete(:stack_size) || -1
|
193
193
|
tty = opts.delete('tty') || opts.delete(:tty) || false
|
194
194
|
msgs = Docker::MessagesStack.new(stack_size)
|
195
|
-
excon_params = {response_block: Docker::Util.attach_for(block, msgs, tty)}
|
195
|
+
excon_params = {response_block: Docker::Util.attach_for(block, msgs, tty), idempotent: false}
|
196
196
|
|
197
197
|
connection.get(path_for(:logs), opts, excon_params)
|
198
198
|
msgs.messages.join
|
@@ -266,16 +266,6 @@ class Docker::Container
|
|
266
266
|
end
|
267
267
|
end
|
268
268
|
|
269
|
-
def copy(path, &block)
|
270
|
-
connection.post(
|
271
|
-
path_for(:copy),
|
272
|
-
{},
|
273
|
-
body: MultiJson.dump('Resource' => path),
|
274
|
-
response_block: block
|
275
|
-
)
|
276
|
-
self
|
277
|
-
end
|
278
|
-
|
279
269
|
def archive_out(path, &block)
|
280
270
|
connection.get(
|
281
271
|
path_for(:archive),
|
@@ -343,7 +333,7 @@ class Docker::Container
|
|
343
333
|
|
344
334
|
# Return the container with specified ID
|
345
335
|
def self.get(id, opts = {}, conn = Docker.connection)
|
346
|
-
container_json = conn.get("/containers/#{
|
336
|
+
container_json = conn.get("/containers/#{id}/json", opts)
|
347
337
|
hash = Docker::Util.parse_json(container_json) || {}
|
348
338
|
new(conn, hash)
|
349
339
|
end
|
data/lib/docker/event.rb
CHANGED
@@ -29,7 +29,9 @@ class Docker::Event
|
|
29
29
|
|
30
30
|
def stream(opts = {}, conn = Docker.connection, &block)
|
31
31
|
conn.get('/events', opts, :response_block => lambda { |b, r, t|
|
32
|
-
|
32
|
+
b.each_line do |line|
|
33
|
+
block.call(new_event(line, r, t))
|
34
|
+
end
|
33
35
|
})
|
34
36
|
end
|
35
37
|
|
data/lib/docker/exec.rb
CHANGED
@@ -19,6 +19,13 @@ class Docker::Exec
|
|
19
19
|
# @return [Docker::Exec] self
|
20
20
|
def self.create(options = {}, conn = Docker.connection)
|
21
21
|
container = options.delete('Container')
|
22
|
+
|
23
|
+
# Podman does not attach these by default but does require them to be attached
|
24
|
+
if ::Docker.podman?(conn)
|
25
|
+
options['AttachStderr'] = true if options['AttachStderr'].nil?
|
26
|
+
options['AttachStdout'] = true if options['AttachStdout'].nil?
|
27
|
+
end
|
28
|
+
|
22
29
|
resp = conn.post("/containers/#{container}/exec", {},
|
23
30
|
body: MultiJson.dump(options))
|
24
31
|
hash = Docker::Util.parse_json(resp) || {}
|
data/lib/docker/image.rb
CHANGED
@@ -65,7 +65,16 @@ class Docker::Image
|
|
65
65
|
|
66
66
|
# Remove the Image from the server.
|
67
67
|
def remove(opts = {})
|
68
|
-
name = opts.delete(:name)
|
68
|
+
name = opts.delete(:name)
|
69
|
+
|
70
|
+
unless name
|
71
|
+
if ::Docker.podman?(connection)
|
72
|
+
name = self.id.split(':').last
|
73
|
+
else
|
74
|
+
name = self.id
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
69
78
|
connection.delete("/images/#{name}", opts)
|
70
79
|
end
|
71
80
|
alias_method :delete, :remove
|
@@ -126,7 +135,7 @@ class Docker::Image
|
|
126
135
|
|
127
136
|
# Return a specific image.
|
128
137
|
def get(id, opts = {}, conn = Docker.connection)
|
129
|
-
image_json = conn.get("/images/#{
|
138
|
+
image_json = conn.get("/images/#{id}/json", opts)
|
130
139
|
hash = Docker::Util.parse_json(image_json) || {}
|
131
140
|
new(conn, hash)
|
132
141
|
end
|
@@ -174,7 +183,7 @@ class Docker::Image
|
|
174
183
|
# By using compare_by_identity we can create a Hash that has
|
175
184
|
# the same key multiple times.
|
176
185
|
query = {}.tap(&:compare_by_identity)
|
177
|
-
Array(names).each { |name| query['names'.dup] =
|
186
|
+
Array(names).each { |name| query['names'.dup] = name }
|
178
187
|
conn.get(
|
179
188
|
'/images/get',
|
180
189
|
query,
|
@@ -227,7 +236,16 @@ class Docker::Image
|
|
227
236
|
# Import an Image from the output of Docker::Container#export. The first
|
228
237
|
# argument may either be a File or URI.
|
229
238
|
def import(imp, opts = {}, conn = Docker.connection)
|
230
|
-
open
|
239
|
+
require 'open-uri'
|
240
|
+
|
241
|
+
# This differs after Ruby 2.4
|
242
|
+
if URI.public_methods.include?(:open)
|
243
|
+
munged_open = URI.method(:open)
|
244
|
+
else
|
245
|
+
munged_open = self.method(:open)
|
246
|
+
end
|
247
|
+
|
248
|
+
munged_open.call(imp) do |io|
|
231
249
|
import_stream(opts, conn) do
|
232
250
|
io.read(Excon.defaults[:chunk_size]).to_s
|
233
251
|
end
|
data/lib/docker/network.rb
CHANGED
@@ -34,7 +34,7 @@ class Docker::Network
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def reload
|
37
|
-
network_json = @connection.get("/networks/#{
|
37
|
+
network_json = @connection.get("/networks/#{@id}")
|
38
38
|
hash = Docker::Util.parse_json(network_json) || {}
|
39
39
|
@info = hash
|
40
40
|
end
|
@@ -51,7 +51,7 @@ class Docker::Network
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def get(id, opts = {}, conn = Docker.connection)
|
54
|
-
network_json = conn.get("/networks/#{
|
54
|
+
network_json = conn.get("/networks/#{id}", opts)
|
55
55
|
hash = Docker::Util.parse_json(network_json) || {}
|
56
56
|
new(conn, hash)
|
57
57
|
end
|
@@ -62,7 +62,7 @@ class Docker::Network
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def remove(id, opts = {}, conn = Docker.connection)
|
65
|
-
conn.delete("/networks/#{
|
65
|
+
conn.delete("/networks/#{id}", opts)
|
66
66
|
nil
|
67
67
|
end
|
68
68
|
alias_method :delete, :remove
|
data/lib/docker/util.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
# This module holds shared logic that doesn't really belong anywhere else in the
|
2
4
|
# gem.
|
3
5
|
module Docker::Util
|
4
6
|
# http://www.tldp.org/LDP/GNU-Linux-Tools-Summary/html/x11655.htm#STANDARD-WILDCARDS
|
5
|
-
GLOB_WILDCARDS = /[\?\*\[\{]/
|
7
|
+
GLOB_WILDCARDS = /[\?\*\[\{\]\}]/
|
6
8
|
|
7
9
|
include Docker::Error
|
8
10
|
|
@@ -142,10 +144,35 @@ module Docker::Util
|
|
142
144
|
File.new(tempfile.path, 'r')
|
143
145
|
end
|
144
146
|
|
147
|
+
|
148
|
+
# return the set of files that form the docker context
|
149
|
+
# implement this logic https://docs.docker.com/engine/reference/builder/#dockerignore-file
|
150
|
+
def docker_context(directory)
|
151
|
+
all_files = glob_all_files(File.join(directory, "**/*"))
|
152
|
+
dockerignore = File.join(directory, '.dockerignore')
|
153
|
+
return all_files unless all_files.include?(dockerignore)
|
154
|
+
|
155
|
+
# Iterate over valid lines, starting with the initial glob as working set
|
156
|
+
File
|
157
|
+
.read(dockerignore) # https://docs.docker.com/engine/reference/builder/#dockerignore-file
|
158
|
+
.each_line # "a newline-separated list of patterns"
|
159
|
+
.map(&:strip) # "A preprocessing step removes leading and trailing whitespace"
|
160
|
+
.reject(&:empty?) # "Lines that are blank after preprocessing are ignored"
|
161
|
+
.reject { |p| p.start_with?('#') } # "if [a line starts with `#`], then this line is considered as a comment"
|
162
|
+
.each_with_object(Set.new(all_files)) do |p, working_set|
|
163
|
+
# determine the pattern (p) and whether it is to be added or removed from context
|
164
|
+
add = p.start_with?("!")
|
165
|
+
# strip leading "!" from pattern p, then prepend the base directory
|
166
|
+
matches = dockerignore_compatible_glob(File.join(directory, add ? p[1..-1] : p))
|
167
|
+
# add or remove the matched items as indicated in the ignore file
|
168
|
+
add ? working_set.merge(matches) : working_set.replace(working_set.difference(matches))
|
169
|
+
end
|
170
|
+
.to_a
|
171
|
+
end
|
172
|
+
|
145
173
|
def create_relative_dir_tar(directory, output)
|
146
174
|
Gem::Package::TarWriter.new(output) do |tar|
|
147
|
-
files =
|
148
|
-
remove_ignored_files!(directory, files)
|
175
|
+
files = docker_context(directory)
|
149
176
|
|
150
177
|
files.each do |prefixed_file_name|
|
151
178
|
stat = File.stat(prefixed_file_name)
|
@@ -241,8 +268,9 @@ module Docker::Util
|
|
241
268
|
|
242
269
|
def build_config_header(credentials)
|
243
270
|
if credentials.is_a?(String)
|
244
|
-
credentials =
|
271
|
+
credentials = MultiJson.load(credentials, symbolize_keys: true)
|
245
272
|
end
|
273
|
+
|
246
274
|
header = MultiJson.dump(
|
247
275
|
credentials[:serveraddress].to_s => {
|
248
276
|
'username' => credentials[:username].to_s,
|
@@ -258,21 +286,23 @@ module Docker::Util
|
|
258
286
|
}
|
259
287
|
end
|
260
288
|
|
261
|
-
|
262
|
-
|
289
|
+
# do a directory glob that matches .dockerignore behavior
|
290
|
+
# specifically: matched directories are considered a recursive match
|
291
|
+
def dockerignore_compatible_glob(pattern)
|
292
|
+
begin
|
293
|
+
some_dirs, some_files = glob_all_files(pattern).partition { |f| File.directory?(f) }
|
294
|
+
# since all directories will be re-processed with a /**/* glob, we can preemptively
|
295
|
+
# eliminate any whose parent directory is already in this set. This saves significant time.
|
296
|
+
some_files + some_dirs.reject { |d| some_dirs.any? { |pd| d.start_with?(pd) && d != pd } }
|
297
|
+
end.each_with_object(Set.new) do |f, acc|
|
298
|
+
# expand any directories by globbing; flatten results
|
299
|
+
acc.merge(File.directory?(f) ? glob_all_files("#{f}/**/*") : [f])
|
300
|
+
end
|
263
301
|
end
|
264
302
|
|
265
|
-
def
|
266
|
-
|
267
|
-
|
268
|
-
ignored_files(directory, ignore).each { |f| files.delete(f) }
|
303
|
+
def glob_all_files(pattern)
|
304
|
+
# globs of "a_dir/**/*" can return "a_dir/.", so explicitly reject those
|
305
|
+
(Dir.glob(pattern, File::FNM_DOTMATCH) - ['..', '.']).reject { |p| p.end_with?("/.") }
|
269
306
|
end
|
270
307
|
|
271
|
-
def ignored_files(directory, ignore_file)
|
272
|
-
patterns = File.read(ignore_file).split("\n").each(&:strip!)
|
273
|
-
patterns.reject! { |p| p.empty? || p.start_with?('#') }
|
274
|
-
patterns.map! { |p| File.join(directory, p) }
|
275
|
-
patterns.map! { |p| File.directory?(p) ? "#{p}/**/*" : p }
|
276
|
-
patterns.flat_map { |p| p =~ GLOB_WILDCARDS ? glob_all_files(p) : p }
|
277
|
-
end
|
278
308
|
end
|
data/lib/docker/version.rb
CHANGED
data/lib/docker.rb
CHANGED
@@ -106,17 +106,27 @@ module Docker
|
|
106
106
|
|
107
107
|
# Get the version of Go, Docker, and optionally the Git commit.
|
108
108
|
def version(connection = self.connection)
|
109
|
-
|
109
|
+
connection.version
|
110
110
|
end
|
111
111
|
|
112
112
|
# Get more information about the Docker server.
|
113
113
|
def info(connection = self.connection)
|
114
|
-
|
114
|
+
connection.info
|
115
115
|
end
|
116
116
|
|
117
117
|
# Ping the Docker server.
|
118
118
|
def ping(connection = self.connection)
|
119
|
-
connection.
|
119
|
+
connection.ping
|
120
|
+
end
|
121
|
+
|
122
|
+
# Determine if the server is podman or docker.
|
123
|
+
def podman?(connection = self.connection)
|
124
|
+
connection.podman?
|
125
|
+
end
|
126
|
+
|
127
|
+
# Determine if the session is rootless.
|
128
|
+
def rootless?(connection = self.connection)
|
129
|
+
connection.rootless?
|
120
130
|
end
|
121
131
|
|
122
132
|
# Login to the Docker registry.
|
@@ -129,19 +139,8 @@ module Docker
|
|
129
139
|
raise Docker::Error::AuthenticationError
|
130
140
|
end
|
131
141
|
|
132
|
-
# When the correct version of Docker is installed, returns true. Otherwise,
|
133
|
-
# raises a VersionError.
|
134
|
-
def validate_version!
|
135
|
-
Docker.info
|
136
|
-
true
|
137
|
-
rescue Docker::Error::TimeoutError
|
138
|
-
raise
|
139
|
-
rescue Docker::Error::DockerError
|
140
|
-
raise Docker::Error::VersionError, "Expected API Version: #{API_VERSION}"
|
141
|
-
end
|
142
|
-
|
143
142
|
module_function :default_socket_url, :env_url, :url, :url=, :env_options,
|
144
143
|
:options, :options=, :creds, :creds=, :logger, :logger=,
|
145
144
|
:connection, :reset!, :reset_connection!, :version, :info,
|
146
|
-
:ping, :
|
145
|
+
:ping, :podman?, :rootless?, :authenticate!, :ssl_options
|
147
146
|
end
|
@@ -1,11 +1,13 @@
|
|
1
1
|
module Excon
|
2
|
-
VALID_REQUEST_KEYS << :hijack_block
|
3
|
-
|
4
2
|
module Middleware
|
5
3
|
# Hijack is an Excon middleware which parses response headers and then
|
6
4
|
# yields the underlying TCP socket for raw TCP communication (used to
|
7
5
|
# attach to STDIN of containers).
|
8
6
|
class Hijack < Base
|
7
|
+
def self.valid_parameter_keys
|
8
|
+
[:hijack_block].freeze
|
9
|
+
end
|
10
|
+
|
9
11
|
def build_response(status, socket)
|
10
12
|
response = {
|
11
13
|
:body => '',
|
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:
|
4
|
+
version: 2.3.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:
|
11
|
+
date: 2024-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: excon
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.64.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.64.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: multi_json
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -175,7 +175,7 @@ files:
|
|
175
175
|
- lib/docker/version.rb
|
176
176
|
- lib/docker/volume.rb
|
177
177
|
- lib/excon/middlewares/hijack.rb
|
178
|
-
homepage: https://github.com/
|
178
|
+
homepage: https://github.com/upserve/docker-api
|
179
179
|
licenses:
|
180
180
|
- MIT
|
181
181
|
metadata: {}
|
@@ -194,10 +194,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
194
194
|
- !ruby/object:Gem::Version
|
195
195
|
version: '0'
|
196
196
|
requirements: []
|
197
|
-
|
198
|
-
rubygems_version: 2.4.6
|
197
|
+
rubygems_version: 3.1.6
|
199
198
|
signing_key:
|
200
199
|
specification_version: 4
|
201
200
|
summary: A simple REST client for the Docker Remote API
|
202
201
|
test_files: []
|
203
|
-
has_rdoc:
|