docker-api 1.34.2 → 2.4.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2bab1ec9ebee2836515645ecde36f9300cfc3bc3
4
- data.tar.gz: 2a27af4bbb6d02cf0e9720cd9fa92b3287e9e7fa
2
+ SHA256:
3
+ metadata.gz: c8c844030bda8d245234ddd5d977ad5202b9a2f0a2e34175579790d79e6f584b
4
+ data.tar.gz: 5b793f7689d091a8a765853511e4f0f8f495338250cdec62bce30fc7a83d5117
5
5
  SHA512:
6
- metadata.gz: d2557d86505b8ccf1c90fa3a6d016ab63d74d90cb5fc4b7596feded67ffc7e9efc8dbe64a22bdd3116a88c6f2d6609a155c4c1c937414644a6b631ad512f102b
7
- data.tar.gz: fde8c2bf4f3cc08f7cb8b9bdc534ba455b339d3e02d3ebd6c0f26d8b4b9f996aade36a0a6a31128da2643891a1bee598be3ea38e1e07c1a57c77c2678a9f293d
6
+ metadata.gz: d5ce08a8dfbe1e5377ceb62d8186e4973ca6f7fa8d166bd9177f8f4a3338dc2dfeb3d735d3c54e31b15373f4124cc87d509d369a34e0f1598291105a4593947f
7
+ data.tar.gz: d27a38af366bbb20febcc3699238a56f5c52d24394780c25d3caf72bc6f9314fb8bae6dd9c7f53cd5ff30558f5bbc353d22fc9f236913a2d8786488c9a702aea
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) [![travis-ci](https://travis-ci.org/swipely/docker-api.svg?branch=master)](https://travis-ci.org/swipely/docker-api) [![Code Climate](https://codeclimate.com/github/swipely/docker-api.svg)](https://codeclimate.com/github/swipely/docker-api) [![Dependency Status](https://gemnasium.com/swipely/docker-api.svg)](https://gemnasium.com/swipely/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 Remote API](https://docs.docker.com/reference/api/docker_remote_api/). Every method listed there is implemented. At the time of this writing, docker-api is meant to interface with Docker version 1.3.*
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/swipely/dockly) gem. Dockly provides a simple DSL for describing Docker containers that install as Debian packages and are controlled by upstart scripts.
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/installation/#installation), and then run:
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](http://www.github.com/geemus/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.
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.
data/lib/docker/base.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This class is a base class for Docker Container and Image.
2
4
  # It is implementing accessor methods for the models attributes.
3
5
  module Docker::Base
@@ -1,6 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This class represents a Connection to a Docker server. The Connection is
2
4
  # immutable in that once the url and options is set they cannot be changed.
3
5
  class Docker::Connection
6
+ require 'docker/util'
7
+ require 'docker/error'
8
+
4
9
  include Docker::Error
5
10
 
6
11
  attr_reader :url, :options
@@ -35,21 +40,58 @@ class Docker::Connection
35
40
 
36
41
  # Send a request to the server with the `
37
42
  def request(*args, &block)
43
+ retries ||= 0
38
44
  request = compile_request_params(*args, &block)
39
45
  log_request(request)
40
- resource.request(request).body
41
- rescue Excon::Errors::BadRequest => ex
42
- raise ClientError, ex.response.body
43
- rescue Excon::Errors::Unauthorized => ex
44
- raise UnauthorizedError, ex.response.body
45
- rescue Excon::Errors::NotFound => ex
46
- raise NotFoundError, ex.response.body
47
- rescue Excon::Errors::Conflict => ex
48
- raise ConflictError, ex.response.body
49
- rescue Excon::Errors::InternalServerError => ex
50
- raise ServerError, ex.response.body
51
- rescue Excon::Errors::Timeout => ex
52
- raise TimeoutError, ex.message
46
+ begin
47
+ resource.request(request).body
48
+ rescue Excon::Errors::BadRequest => ex
49
+ if retries < 2
50
+ response_cause = ''
51
+ begin
52
+ response_cause = JSON.parse(ex.response.body)['cause']
53
+ rescue JSON::ParserError
54
+ #noop
55
+ end
56
+
57
+ if response_cause.is_a?(String)
58
+ # The error message will tell the application type given and then the
59
+ # application type that the message should be
60
+ #
61
+ # This is not perfect since it relies on processing a message that
62
+ # could change in the future. However, it should be a good stop-gap
63
+ # until all methods are updated to pass in the appropriate content
64
+ # type.
65
+ #
66
+ # A current example message is:
67
+ # * 'Content-Type: application/json is not supported. Should be "application/x-tar"'
68
+ matches = response_cause.delete('"\'').scan(%r{(application/\S+)})
69
+ unless matches.count < 2
70
+ Docker.logger.warn(
71
+ <<~RETRY_WARNING
72
+ Automatically retrying with content type '#{response_cause}'
73
+ Original Error: #{ex}
74
+ RETRY_WARNING
75
+ ) if Docker.logger
76
+
77
+ request[:headers]['Content-Type'] = matches.last.first
78
+ retries += 1
79
+ retry
80
+ end
81
+ end
82
+ end
83
+ raise ClientError, ex.response.body
84
+ rescue Excon::Errors::Unauthorized => ex
85
+ raise UnauthorizedError, ex.response.body
86
+ rescue Excon::Errors::NotFound => ex
87
+ raise NotFoundError, ex.response.body
88
+ rescue Excon::Errors::Conflict => ex
89
+ raise ConflictError, ex.response.body
90
+ rescue Excon::Errors::InternalServerError => ex
91
+ raise ServerError, ex.response.body
92
+ rescue Excon::Errors::Timeout => ex
93
+ raise TimeoutError, ex.message
94
+ end
53
95
  end
54
96
 
55
97
  def log_request(request)
@@ -60,13 +102,38 @@ class Docker::Connection
60
102
  end
61
103
  end
62
104
 
105
+ def to_s
106
+ "Docker::Connection { :url => #{url}, :options => #{options} }"
107
+ end
108
+
63
109
  # Delegate all HTTP methods to the #request.
64
110
  [:get, :put, :post, :delete].each do |method|
65
111
  define_method(method) { |*args, &block| request(method, *args, &block) }
66
112
  end
67
113
 
68
- def to_s
69
- "Docker::Connection { :url => #{url}, :options => #{options} }"
114
+ # Common attribute requests
115
+ def info
116
+ Docker::Util.parse_json(get('/info'))
117
+ end
118
+
119
+ def ping
120
+ get('/_ping')
121
+ end
122
+
123
+ def podman?
124
+ @podman ||= !(
125
+ Array(version['Components']).find do |component|
126
+ component['Name'].include?('Podman')
127
+ end
128
+ ).nil?
129
+ end
130
+
131
+ def rootless?
132
+ @rootless ||= (info['Rootless'] == true)
133
+ end
134
+
135
+ def version
136
+ @version ||= Docker::Util.parse_json(get('/version'))
70
137
  end
71
138
 
72
139
  private
@@ -80,7 +147,7 @@ private
80
147
  user_agent = "Swipely/Docker-API #{Docker::VERSION}"
81
148
  {
82
149
  :method => http_method,
83
- :path => "/v#{Docker::API_VERSION}#{path}",
150
+ :path => path,
84
151
  :query => query,
85
152
  :headers => { 'Content-Type' => content_type,
86
153
  'User-Agent' => user_agent,
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This class represents a Docker Container. It's important to note that nothing
2
4
  # is cached so that the information is always up to date.
3
5
  class Docker::Container
@@ -189,7 +191,7 @@ class Docker::Container
189
191
  end
190
192
 
191
193
  def streaming_logs(opts = {}, &block)
192
- stack_size = opts.delete('stack_size') || -1
194
+ stack_size = opts.delete('stack_size') || opts.delete(:stack_size) || -1
193
195
  tty = opts.delete('tty') || opts.delete(:tty) || false
194
196
  msgs = Docker::MessagesStack.new(stack_size)
195
197
  excon_params = {response_block: Docker::Util.attach_for(block, msgs, tty), idempotent: false}
@@ -266,16 +268,6 @@ class Docker::Container
266
268
  end
267
269
  end
268
270
 
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
271
  def archive_out(path, &block)
280
272
  connection.get(
281
273
  path_for(:archive),
@@ -343,7 +335,7 @@ class Docker::Container
343
335
 
344
336
  # Return the container with specified ID
345
337
  def self.get(id, opts = {}, conn = Docker.connection)
346
- container_json = conn.get("/containers/#{URI.encode(id)}/json", opts)
338
+ container_json = conn.get("/containers/#{id}/json", opts)
347
339
  hash = Docker::Util.parse_json(container_json) || {}
348
340
  new(conn, hash)
349
341
  end
data/lib/docker/error.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This module holds the Errors for the gem.
2
4
  module Docker::Error
3
5
 
data/lib/docker/event.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This class represents a Docker Event.
2
4
  class Docker::Event
3
5
  include Docker::Error
@@ -29,7 +31,9 @@ class Docker::Event
29
31
 
30
32
  def stream(opts = {}, conn = Docker.connection, &block)
31
33
  conn.get('/events', opts, :response_block => lambda { |b, r, t|
32
- block.call(new_event(b, r, t))
34
+ b.each_line do |line|
35
+ block.call(new_event(line, r, t))
36
+ end
33
37
  })
34
38
  end
35
39
 
data/lib/docker/exec.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This class represents a Docker Exec Instance.
2
4
  class Docker::Exec
3
5
  include Docker::Base
@@ -19,6 +21,13 @@ class Docker::Exec
19
21
  # @return [Docker::Exec] self
20
22
  def self.create(options = {}, conn = Docker.connection)
21
23
  container = options.delete('Container')
24
+
25
+ # Podman does not attach these by default but does require them to be attached
26
+ if ::Docker.podman?(conn)
27
+ options['AttachStderr'] = true if options['AttachStderr'].nil?
28
+ options['AttachStdout'] = true if options['AttachStdout'].nil?
29
+ end
30
+
22
31
  resp = conn.post("/containers/#{container}/exec", {},
23
32
  body: MultiJson.dump(options))
24
33
  hash = Docker::Util.parse_json(resp) || {}
data/lib/docker/image.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This class represents a Docker Image.
2
4
  class Docker::Image
3
5
  include Docker::Base
@@ -28,7 +30,7 @@ class Docker::Image
28
30
  repo, tag = Docker::Util.parse_repo_tag(repo_tag)
29
31
  raise ArgumentError, "Image does not have a name to push." if repo.nil?
30
32
 
31
- body = ""
33
+ body = +""
32
34
  credentials = creds || Docker.creds || {}
33
35
  headers = Docker::Util.build_auth_header(credentials)
34
36
  opts = {:tag => tag}.merge(options)
@@ -65,7 +67,16 @@ class Docker::Image
65
67
 
66
68
  # Remove the Image from the server.
67
69
  def remove(opts = {})
68
- name = opts.delete(:name) || self.id
70
+ name = opts.delete(:name)
71
+
72
+ unless name
73
+ if ::Docker.podman?(connection)
74
+ name = self.id.split(':').last
75
+ else
76
+ name = self.id
77
+ end
78
+ end
79
+
69
80
  connection.delete("/images/#{name}", opts)
70
81
  end
71
82
  alias_method :delete, :remove
@@ -110,7 +121,7 @@ class Docker::Image
110
121
  def create(opts = {}, creds = nil, conn = Docker.connection, &block)
111
122
  credentials = creds.nil? ? Docker.creds : MultiJson.dump(creds)
112
123
  headers = credentials && Docker::Util.build_auth_header(credentials) || {}
113
- body = ''
124
+ body = +''
114
125
  conn.post(
115
126
  '/images/create',
116
127
  opts,
@@ -126,7 +137,7 @@ class Docker::Image
126
137
 
127
138
  # Return a specific image.
128
139
  def get(id, opts = {}, conn = Docker.connection)
129
- image_json = conn.get("/images/#{URI.encode(id)}/json", opts)
140
+ image_json = conn.get("/images/#{id}/json", opts)
130
141
  hash = Docker::Util.parse_json(image_json) || {}
131
142
  new(conn, hash)
132
143
  end
@@ -159,7 +170,7 @@ class Docker::Image
159
170
  end
160
171
  nil
161
172
  else
162
- string = ''
173
+ string = +''
163
174
  save_stream(names, {}, conn, &response_block_for_save(string))
164
175
  string
165
176
  end
@@ -174,7 +185,7 @@ class Docker::Image
174
185
  # By using compare_by_identity we can create a Hash that has
175
186
  # the same key multiple times.
176
187
  query = {}.tap(&:compare_by_identity)
177
- Array(names).each { |name| query['names'.dup] = URI.encode(name) }
188
+ Array(names).each { |name| query['names'.dup] = name }
178
189
  conn.get(
179
190
  '/images/get',
180
191
  query,
@@ -187,7 +198,7 @@ class Docker::Image
187
198
  def load(tar, opts = {}, conn = Docker.connection, creds = nil, &block)
188
199
  headers = build_headers(creds)
189
200
  io = tar.is_a?(String) ? File.open(tar, 'rb') : tar
190
- body = ""
201
+ body = +""
191
202
  conn.post(
192
203
  '/images/load',
193
204
  opts,
@@ -227,7 +238,16 @@ class Docker::Image
227
238
  # Import an Image from the output of Docker::Container#export. The first
228
239
  # argument may either be a File or URI.
229
240
  def import(imp, opts = {}, conn = Docker.connection)
230
- open(imp) do |io|
241
+ require 'open-uri'
242
+
243
+ # This differs after Ruby 2.4
244
+ if URI.public_methods.include?(:open)
245
+ munged_open = URI.method(:open)
246
+ else
247
+ munged_open = self.method(:open)
248
+ end
249
+
250
+ munged_open.call(imp) do |io|
231
251
  import_stream(opts, conn) do
232
252
  io.read(Excon.defaults[:chunk_size]).to_s
233
253
  end
@@ -249,7 +269,7 @@ class Docker::Image
249
269
 
250
270
  # Given a Dockerfile as a string, builds an Image.
251
271
  def build(commands, opts = {}, connection = Docker.connection, &block)
252
- body = ""
272
+ body = +""
253
273
  connection.post(
254
274
  '/build', opts,
255
275
  :body => Docker::Util.create_tar('Dockerfile' => commands),
@@ -270,7 +290,7 @@ class Docker::Image
270
290
  headers = build_headers(creds)
271
291
 
272
292
  # The response_block passed to Excon will build up this body variable.
273
- body = ""
293
+ body = +""
274
294
  connection.post(
275
295
  '/build', opts,
276
296
  :headers => headers,
@@ -322,7 +342,7 @@ class Docker::Image
322
342
  # Convience method to get the Dockerfile for a file hash and a path to
323
343
  # output to.
324
344
  def dockerfile_for(file_hash, output_path)
325
- dockerfile = "from #{self.id}\n"
345
+ dockerfile = +"from #{self.id}\n"
326
346
 
327
347
  file_hash.keys.each do |basename|
328
348
  dockerfile << "add #{basename} #{output_path}\n"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This class represents all the messages either received by chunks from attach
2
4
  class Docker::Messages
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This class represents a messages stack
2
4
  class Docker::MessagesStack
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This class represents a Docker Network.
2
4
  class Docker::Network
3
5
  include Docker::Base
@@ -34,7 +36,7 @@ class Docker::Network
34
36
  end
35
37
 
36
38
  def reload
37
- network_json = @connection.get("/networks/#{URI.encode(@id)}")
39
+ network_json = @connection.get("/networks/#{@id}")
38
40
  hash = Docker::Util.parse_json(network_json) || {}
39
41
  @info = hash
40
42
  end
@@ -51,7 +53,7 @@ class Docker::Network
51
53
  end
52
54
 
53
55
  def get(id, opts = {}, conn = Docker.connection)
54
- network_json = conn.get("/networks/#{URI.encode(id)}", opts)
56
+ network_json = conn.get("/networks/#{id}", opts)
55
57
  hash = Docker::Util.parse_json(network_json) || {}
56
58
  new(conn, hash)
57
59
  end
@@ -62,7 +64,7 @@ class Docker::Network
62
64
  end
63
65
 
64
66
  def remove(id, opts = {}, conn = Docker.connection)
65
- conn.delete("/networks/#{URI.encode(id)}", opts)
67
+ conn.delete("/networks/#{id}", opts)
66
68
  nil
67
69
  end
68
70
  alias_method :delete, :remove
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This class allows image-based tasks to be created.
2
4
  class Docker::ImageTask < Rake::Task
3
5
  def self.scope_name(_scope, task_name)
data/lib/docker/util.rb CHANGED
@@ -1,8 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+
1
5
  # This module holds shared logic that doesn't really belong anywhere else in the
2
6
  # gem.
3
7
  module Docker::Util
4
8
  # http://www.tldp.org/LDP/GNU-Linux-Tools-Summary/html/x11655.htm#STANDARD-WILDCARDS
5
- GLOB_WILDCARDS = /[\?\*\[\{]/
9
+ GLOB_WILDCARDS = /[\?\*\[\{\]\}]/
6
10
 
7
11
  include Docker::Error
8
12
 
@@ -142,10 +146,35 @@ module Docker::Util
142
146
  File.new(tempfile.path, 'r')
143
147
  end
144
148
 
149
+
150
+ # return the set of files that form the docker context
151
+ # implement this logic https://docs.docker.com/engine/reference/builder/#dockerignore-file
152
+ def docker_context(directory)
153
+ all_files = glob_all_files(File.join(directory, "**/*"))
154
+ dockerignore = File.join(directory, '.dockerignore')
155
+ return all_files unless all_files.include?(dockerignore)
156
+
157
+ # Iterate over valid lines, starting with the initial glob as working set
158
+ File
159
+ .read(dockerignore) # https://docs.docker.com/engine/reference/builder/#dockerignore-file
160
+ .each_line # "a newline-separated list of patterns"
161
+ .map(&:strip) # "A preprocessing step removes leading and trailing whitespace"
162
+ .reject(&:empty?) # "Lines that are blank after preprocessing are ignored"
163
+ .reject { |p| p.start_with?('#') } # "if [a line starts with `#`], then this line is considered as a comment"
164
+ .each_with_object(Set.new(all_files)) do |p, working_set|
165
+ # determine the pattern (p) and whether it is to be added or removed from context
166
+ add = p.start_with?("!")
167
+ # strip leading "!" from pattern p, then prepend the base directory
168
+ matches = dockerignore_compatible_glob(File.join(directory, add ? p[1..-1] : p))
169
+ # add or remove the matched items as indicated in the ignore file
170
+ add ? working_set.merge(matches) : working_set.replace(working_set.difference(matches))
171
+ end
172
+ .to_a
173
+ end
174
+
145
175
  def create_relative_dir_tar(directory, output)
146
176
  Gem::Package::TarWriter.new(output) do |tar|
147
- files = glob_all_files(File.join(directory, "**/*"))
148
- remove_ignored_files!(directory, files)
177
+ files = docker_context(directory)
149
178
 
150
179
  files.each do |prefixed_file_name|
151
180
  stat = File.stat(prefixed_file_name)
@@ -259,21 +288,23 @@ module Docker::Util
259
288
  }
260
289
  end
261
290
 
262
- def glob_all_files(pattern)
263
- Dir.glob(pattern, File::FNM_DOTMATCH) - ['..', '.']
291
+ # do a directory glob that matches .dockerignore behavior
292
+ # specifically: matched directories are considered a recursive match
293
+ def dockerignore_compatible_glob(pattern)
294
+ begin
295
+ some_dirs, some_files = glob_all_files(pattern).partition { |f| File.directory?(f) }
296
+ # since all directories will be re-processed with a /**/* glob, we can preemptively
297
+ # eliminate any whose parent directory is already in this set. This saves significant time.
298
+ some_files + some_dirs.reject { |d| some_dirs.any? { |pd| d.start_with?(pd) && d != pd } }
299
+ end.each_with_object(Set.new) do |f, acc|
300
+ # expand any directories by globbing; flatten results
301
+ acc.merge(File.directory?(f) ? glob_all_files("#{f}/**/*") : [f])
302
+ end
264
303
  end
265
304
 
266
- def remove_ignored_files!(directory, files)
267
- ignore = File.join(directory, '.dockerignore')
268
- return unless files.include?(ignore)
269
- ignored_files(directory, ignore).each { |f| files.delete(f) }
305
+ def glob_all_files(pattern)
306
+ # globs of "a_dir/**/*" can return "a_dir/.", so explicitly reject those
307
+ (Dir.glob(pattern, File::FNM_DOTMATCH) - ['..', '.']).reject { |p| p.end_with?("/.") }
270
308
  end
271
309
 
272
- def ignored_files(directory, ignore_file)
273
- patterns = File.read(ignore_file).split("\n").each(&:strip!)
274
- patterns.reject! { |p| p.empty? || p.start_with?('#') }
275
- patterns.map! { |p| File.join(directory, p) }
276
- patterns.map! { |p| File.directory?(p) ? "#{p}/**/*" : p }
277
- patterns.flat_map { |p| p =~ GLOB_WILDCARDS ? glob_all_files(p) : p }
278
- end
279
310
  end
@@ -1,7 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Docker
2
4
  # The version of the docker-api gem.
3
- VERSION = '1.34.2'
4
-
5
- # The version of the compatible Docker remote API.
6
- API_VERSION = '1.16'
5
+ VERSION = '2.4.0'
7
6
  end
data/lib/docker/volume.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # class represents a Docker Volume
2
4
  class Docker::Volume
3
5
  include Docker::Base
data/lib/docker-api.rb CHANGED
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'docker'
data/lib/docker.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'cgi'
2
4
  require 'multi_json'
3
5
  require 'excon'
@@ -106,17 +108,27 @@ module Docker
106
108
 
107
109
  # Get the version of Go, Docker, and optionally the Git commit.
108
110
  def version(connection = self.connection)
109
- Util.parse_json(connection.get('/version'))
111
+ connection.version
110
112
  end
111
113
 
112
114
  # Get more information about the Docker server.
113
115
  def info(connection = self.connection)
114
- Util.parse_json(connection.get('/info'))
116
+ connection.info
115
117
  end
116
118
 
117
119
  # Ping the Docker server.
118
120
  def ping(connection = self.connection)
119
- connection.get('/_ping')
121
+ connection.ping
122
+ end
123
+
124
+ # Determine if the server is podman or docker.
125
+ def podman?(connection = self.connection)
126
+ connection.podman?
127
+ end
128
+
129
+ # Determine if the session is rootless.
130
+ def rootless?(connection = self.connection)
131
+ connection.rootless?
120
132
  end
121
133
 
122
134
  # Login to the Docker registry.
@@ -129,19 +141,8 @@ module Docker
129
141
  raise Docker::Error::AuthenticationError
130
142
  end
131
143
 
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
144
  module_function :default_socket_url, :env_url, :url, :url=, :env_options,
144
145
  :options, :options=, :creds, :creds=, :logger, :logger=,
145
146
  :connection, :reset!, :reset_connection!, :version, :info,
146
- :ping, :authenticate!, :validate_version!, :ssl_options
147
+ :ping, :podman?, :rootless?, :authenticate!, :ssl_options
147
148
  end
@@ -1,11 +1,15 @@
1
- module Excon
2
- VALID_REQUEST_KEYS << :hijack_block
1
+ # frozen_string_literal: true
3
2
 
3
+ module Excon
4
4
  module Middleware
5
5
  # Hijack is an Excon middleware which parses response headers and then
6
6
  # yields the underlying TCP socket for raw TCP communication (used to
7
7
  # attach to STDIN of containers).
8
8
  class Hijack < Base
9
+ def self.valid_parameter_keys
10
+ [:hijack_block].freeze
11
+ end
12
+
9
13
  def build_response(status, socket)
10
14
  response = {
11
15
  :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: 1.34.2
4
+ version: 2.4.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: 2018-03-16 00:00:00.000000000 Z
11
+ date: 2024-10-30 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.47.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.47.0
26
+ version: 0.64.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: multi_json
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -80,20 +80,6 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: cane
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: pry
99
85
  requirement: !ruby/object:Gem::Requirement
@@ -175,7 +161,7 @@ files:
175
161
  - lib/docker/version.rb
176
162
  - lib/docker/volume.rb
177
163
  - lib/excon/middlewares/hijack.rb
178
- homepage: https://github.com/swipely/docker-api
164
+ homepage: https://github.com/upserve/docker-api
179
165
  licenses:
180
166
  - MIT
181
167
  metadata: {}
@@ -194,8 +180,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
194
180
  - !ruby/object:Gem::Version
195
181
  version: '0'
196
182
  requirements: []
197
- rubyforge_project:
198
- rubygems_version: 2.5.1
183
+ rubygems_version: 3.1.6
199
184
  signing_key:
200
185
  specification_version: 4
201
186
  summary: A simple REST client for the Docker Remote API