dockerapi 0.11.0 → 0.16.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
  SHA256:
3
- metadata.gz: '09aa5bf2a46df8ad42f1c4833fe7577610af14dde350730787b703e1080fa4c7'
4
- data.tar.gz: 0be7a47781bbc7f75824f65b8fea5d7bcbd11deb98451f2b030856391a68d5c1
3
+ metadata.gz: 8207aa413525c868d4e1c0f57cacf38c19348dee819da2aeb63f390d5ac41f28
4
+ data.tar.gz: 53406674405580c0dcb91c4c32a914ef0de92ce9a9c1132eb7bf046902e5adc8
5
5
  SHA512:
6
- metadata.gz: f0573e091c6cbbc6c2fa3411ca6336a328e4677a656f22bd7d4a036064f8c813523c6a686c2e3ec03df2ec194f65c1b69c6d5be5782c1a1fca80460f3c383db9
7
- data.tar.gz: 5fa96ad226aad3faa2e3a2836948687adf29079b0495e88ceb42424bbe14d2664cab4a8f59a2a795e2f73c9fe59318504a9c454b4964d1b16a04165023c7e8f8
6
+ metadata.gz: be5d82c94e72b29d4341330b3c12f4a2007c6e46813cca6eb6cc8ba3f3a0adae2cd8ef00d0020ed1d59bf5bfc12bf6b22f6b3dd96eb5287ee03f02e14f1bb0ce
7
+ data.tar.gz: f4155422936cd0a4e754d4f32a118662c1d6ace28d788aae51e4d09f09b817519ed7ec0bca9e1955bcb2edc66c5ea111181493e43d398de20e4662d665ac8d2b
@@ -1,3 +1,54 @@
1
+ # 0.16.0
2
+
3
+ `Docker::API::Task#logs` method can now receive a block to replace standard output to stdout behavior.
4
+
5
+ Add `auth_encoder` to provide standard implementation for the authentication header where needed.
6
+
7
+ # 0.15.0
8
+
9
+ `Docker::API::System#events` and `Docker::API::Exec#start` methods can now receive a block to replace standard output to stdout behavior.
10
+
11
+ General refactoring and API documentation.
12
+
13
+ # 0.14.0
14
+
15
+ Method `Docker::API::Container#archive` is splitted in `#get_archive` and `#put_archive` as per Docker API documentation.
16
+
17
+ The following `Docker::API::Container` methods that can now receive a block:
18
+ * logs (output to stdout)
19
+ * attach (output to stdout)
20
+ * stats (output to stdout)
21
+ * export (write file)
22
+ * get_archive (write file)
23
+
24
+ # 0.13.0
25
+
26
+ Add default behavior for file read, write and output to stdout. Whenever a method can receive a block, this default behavior can be replaced.
27
+
28
+ The following `Docker::API::Image` methods that can now receive a block:
29
+ * export (write file)
30
+ * create (output to stdout)
31
+ * build (output to stdout)
32
+
33
+ Default output to stdout can be supressed by setting `Docker::API::PRINT_TO_STDOUT` to `false`
34
+
35
+ Method parameters `params` and `body` will be automatically evaluated whenever they are present in the method's signature.
36
+
37
+ # 0.12.0
38
+
39
+ Add `Docker::API::Plugin` methods:
40
+ * list
41
+ * privileges
42
+ * install
43
+ * details
44
+ * remove
45
+ * enable
46
+ * disable
47
+ * upgrade
48
+ * create
49
+ * push
50
+ * configure
51
+
1
52
  # 0.11.0
2
53
 
3
54
  Add `Docker::API::Task` methods:
@@ -1,14 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dockerapi (0.11.0)
5
- excon (~> 0.74.0)
4
+ dockerapi (0.16.0)
5
+ excon (~> 0.76.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
10
  diff-lcs (1.3)
11
- excon (0.74.0)
11
+ excon (0.76.0)
12
12
  rake (12.3.3)
13
13
  rspec (3.9.0)
14
14
  rspec-core (~> 3.9.0)
data/README.md CHANGED
@@ -1,6 +1,29 @@
1
1
  # dockerapi
2
2
 
3
- Interact directly with Docker API from Ruby code.
3
+ Interact with Docker API directly from Ruby code. Comprehensive implementation (all available endpoints), no local Docker installation required, easily manipulated http responses.
4
+
5
+ * [Installation](#installation)
6
+ * [Usage](#usage)
7
+ * [Images](#images)
8
+ * [Containers](#containers)
9
+ * [Volumes](#volumes)
10
+ * [Network](#network)
11
+ * [System](#system)
12
+ * [Exec](#exec)
13
+ * [Swarm](#swarm)
14
+ * [Node](#node)
15
+ * [Service](#service)
16
+ * [Task](#task)
17
+ * [Secret](#secret)
18
+ * [Config](#config)
19
+ * [Plugin](#plugin)
20
+ * [Connection](#connection)
21
+ * [Requests](#requests)
22
+ * [Response](#response)
23
+ * [Error handling](#error-handling)
24
+ * [Development](#development)
25
+ * [Contributing](#contributing)
26
+ * [License](#license)
4
27
 
5
28
  ## Installation
6
29
 
@@ -8,6 +31,8 @@ Add this line to your application's Gemfile:
8
31
 
9
32
  ```ruby
10
33
  gem 'dockerapi'
34
+ # or
35
+ gem 'dockerapi', github: 'nu12/dockerapi'
11
36
  ```
12
37
 
13
38
  And then execute:
@@ -20,6 +45,12 @@ Or install it yourself as:
20
45
 
21
46
  ## Usage
22
47
 
48
+ The following section will bring you up to speed in order to use most this gem resources with pratical examples.
49
+
50
+ If you need more information about the different Docker API endpoints, please see the [Docker API documentation](https://docs.docker.com/engine/api/v1.40/).
51
+
52
+ For a more detailed and comprehensive documentation about this gem's API, please see the [documentation page](https://rubydoc.info/gems/dockerapi).
53
+
23
54
  ### Images
24
55
 
25
56
  ```ruby
@@ -75,13 +106,16 @@ image.prune(filters: {dangling: {"false": true}})
75
106
  image.commit(container: container, repo: "my/image", tag: "latest", comment: "Comment from commit", author: "dockerapi", pause: false )
76
107
 
77
108
  # Build image from a local tar file
78
- image.build("/path/to/file.tar")
109
+ image.build("/path/to/file.tar", {t: "tag"})
110
+
111
+ # Build image using private repository
112
+ image.build("/path/to/file.tar", {t: "tag"}, {"https://index.docker.io/v1/" => {username: "janedoe", password: "janedoe"}})
79
113
 
80
114
  # Build image from a remote tar file
81
- image.build(nil, remote: "https://url.to/file.tar")
115
+ image.build(nil, {remote: "https://url.to/file.tar", t: "tag"})
82
116
 
83
117
  # Build image from a remote Dockerfile
84
- image.build(nil, remote: "https://url.to/Dockerfile")
118
+ image.build(nil, {remote: "https://url.to/Dockerfile", t: "tag"})
85
119
 
86
120
  # Delete builder cache
87
121
  image.delete_cache
@@ -148,7 +182,10 @@ container.stats("nginx", stream: true)
148
182
  container.export("nginx", "~/exported_container")
149
183
 
150
184
  # Get files from container
151
- container.archive("nginx", "~/html.tar", path: "/usr/share/nginx/html/")
185
+ container.get_archive("nginx", "~/html.tar", path: "/usr/share/nginx/html/")
186
+
187
+ # Send files to container
188
+ container.put_archive("nginx", "~/html.tar", path: "/usr/share/nginx/html/")
152
189
 
153
190
  # Stop container
154
191
  container.stop("nginx")
@@ -391,9 +428,50 @@ config.update("config-name", {version: version}, spec.merge!({ Data: "VEhJUyBJUy
391
428
  config.delete("config-name")
392
429
  ```
393
430
 
431
+ ### Plugin
432
+ ```ruby
433
+ # Connect to local plugin endpoints
434
+ plugin = Docker::API::Plugin.new
435
+
436
+ # List plugins
437
+ plugin.list
438
+
439
+ # List plugin's privileges
440
+ plugin.privileges(remote: "plugin-name")
441
+
442
+ # Install plugin (using defined privileges)
443
+ privileges = plugin.privileges(remote: "plugin-name")
444
+ plugin.install({remote: "plugin-name"}, privileges)
445
+
446
+ # Upgrade plugin (using defined privileges)
447
+ privileges = plugin.privileges(remote: "plugin-name2")
448
+ plugin.upgrade("plugin-name", {remote: "plugin-name2"}, privileges)
449
+
450
+ # Enable plugin
451
+ plugin.enable("plugin-name", timeout: 0)
452
+
453
+ # Disable plugin
454
+ plugin.disable("plugin-name")
455
+
456
+ # Configure plugin
457
+ plugin.configure("plugin-name", ["DEBUG=1"])
458
+
459
+ # Inspect plugin
460
+ plugin.details("plugin-name")
461
+
462
+ # Remove plugin
463
+ plugin.remove("plugin-name")
464
+
465
+ # Create plugin (tar file must contain rootfs folder and config.json file)
466
+ plugin.create("name", "/path/to/file.tar")
467
+
468
+ # Push plugin
469
+ plugin.push("name")
470
+ ```
471
+
394
472
  ### Connection
395
473
 
396
- By default Docker::API::Connection will connect to local Docker socket at `/var/run/docker.sock`. See examples below to use a different path or connect to a remote address.
474
+ By default `Docker::API::Connection` will connect to local Docker socket at `/var/run/docker.sock`. See examples below to use a different path or connect to a remote address.
397
475
 
398
476
  ```ruby
399
477
  # Setting different connections
@@ -465,20 +543,19 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
465
543
 
466
544
  | Class | Tests | Implementation | Refactoring |
467
545
  |---|---|---|---|
468
- | Image | Ok | Ok | 8/7 |
469
- | Container | Ok | Ok | 8/14 |
470
- | Volume | Ok | Ok | 8/21 |
471
- | Network | Ok | Ok | 8/21 |
472
- | System | Ok | Ok | 8/21 |
473
- | Exec | Ok | Ok | 8/21 |
474
- | Swarm | Ok | Ok | 8/28 |
475
- | Node | Ok | Ok | 8/28 |
476
- | Service | Ok | Ok | 8/28 |
477
- | Task | Ok | Ok | 9/4 |
478
- | Secret | Ok | Ok | 9/4 |
479
- | Config | Ok | Ok | 9/4 |
480
- | Distribution | Ok | Ok | 9/4 |
481
- | Plugin | 7/24 | 7/24 | 9/4 |
546
+ | Image | Ok | Ok | Ok |
547
+ | Container | Ok | Ok | Ok |
548
+ | Volume | Ok | Ok | Ok |
549
+ | Network | Ok | Ok | Ok |
550
+ | System | Ok | Ok | Ok |
551
+ | Exec | Ok | Ok | Ok |
552
+ | Swarm | Ok | Ok | Ok |
553
+ | Node | Ok | Ok | Ok |
554
+ | Service | Ok | Ok | Ok |
555
+ | Task | Ok | Ok | Ok |
556
+ | Secret | Ok | Ok | Ok |
557
+ | Config | Ok | Ok | 8/14 |
558
+ | Plugin | Ok | Ok | 8/14 |
482
559
 
483
560
  ## Contributing
484
561
 
@@ -6,8 +6,8 @@ Gem::Specification.new do |spec|
6
6
  spec.authors = ["Alysson A. Costa"]
7
7
  spec.email = ["alysson.avila.costa@gmail.com"]
8
8
 
9
- spec.summary = "Interact directly with Docker API from Ruby code."
10
- spec.description = "Interact directly with Docker API from Ruby code."
9
+ spec.summary = "Interact with Docker API from Ruby code."
10
+ spec.description = "Interact with Docker API directly from Ruby code. Comprehensive implementation (all available endpoints), no local Docker installation required, easily manipulated http responses."
11
11
  spec.homepage = "https://github.com/nu12/dockerapi"
12
12
  spec.license = "MIT"
13
13
  spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
@@ -15,6 +15,7 @@ Gem::Specification.new do |spec|
15
15
  spec.metadata["homepage_uri"] = spec.homepage
16
16
  spec.metadata["source_code_uri"] = "https://github.com/nu12/dockerapi.git"
17
17
  spec.metadata["changelog_uri"] = "https://github.com/nu12/dockerapi/blob/master/CHANGELOG.md"
18
+ spec.metadata["documentation_uri"] = "https://www.rubydoc.info/gems/dockerapi"
18
19
 
19
20
  # Specify which files should be added to the gem when it is released.
20
21
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@@ -25,5 +26,5 @@ Gem::Specification.new do |spec|
25
26
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
27
  spec.require_paths = ["lib"]
27
28
 
28
- spec.add_dependency("excon", "~> 0.74.0")
29
+ spec.add_dependency("excon", "~> 0.76.0")
29
30
  end
@@ -1,38 +1,110 @@
1
- module Docker
2
- module API
3
- class Base
1
+ ##
2
+ # Base class to provide general methods, helpers and implementations accross classes.
3
+ class Docker::API::Base
4
+
5
+ ##
6
+ # Creates new object and sets the validation to happen automatically when method parameters include "params" or "body".
7
+ #
8
+ # @param connection [Docker::API::Connection]: Connection to be used.
9
+ def initialize connection = nil
10
+ raise Docker::API::Error.new("Expected connection to be a Docker::API::Connection class") if connection != nil && !connection.is_a?(Docker::API::Connection)
11
+ @connection = connection || Docker::API::Connection.new
12
+ set_automated_validation
13
+ end
14
+
15
+ private
4
16
 
5
- def initialize connection = nil
6
- raise Docker::API::Error.new("Expect connection to be a Docker::API::Connection class") if connection != nil && !connection.is_a?(Docker::API::Connection)
7
- @connection = connection || Docker::API::Connection.new
8
- end
9
-
10
- private
17
+ ##
18
+ # Outputs to stdout.
19
+ def default_streamer
20
+ streamer = lambda do |chunk, remaining_bytes, total_bytes|
21
+ p chunk.to_s.encode('UTF-8', invalid: :replace, undef: :replace, replace: '?') if Docker::API::PRINT_TO_STDOUT
22
+ end
23
+ streamer
24
+ end
11
25
 
12
- def base_path # TODO: this method to be removed?
13
- "/"
14
- end
26
+ ##
27
+ # Writes file.
28
+ #
29
+ # @param path [String]: Path to the file to be writen.
30
+ def default_writer path
31
+ streamer = lambda do |chunk, remaining_bytes, total_bytes|
32
+ return if "#{chunk}".match(/(No such image)/)
33
+ file = File.open(File.expand_path(path), "wb+")
34
+ file.write(chunk)
35
+ file.close
36
+ end
37
+ streamer
38
+ end
15
39
 
16
- def validate error, permitted, params
17
- return if params[:skip_validation]
18
- unpermitted = params.keys.map(&:to_s) - permitted.map(&:to_s)
19
- raise error.new(permitted, unpermitted) if unpermitted.size > 0
20
- end
40
+ ##
41
+ # Reads file.
42
+ #
43
+ # @param path [String]: Path to the file to be read.
44
+ # @param url [String]: Endpoint URL where the file is going to be sent.
45
+ # @param header [Hash]: Header of the request.
46
+ # @param &block: Replace the default output to stdout behavior.
47
+ def default_reader path, url, header = {"Content-Type" => "application/x-tar"}, &block
48
+ file = File.open(File.expand_path(path), "r")
49
+ response = @connection.request(method: :post, path: url , headers: header, request_block: lambda { file.read(Excon.defaults[:chunk_size]).to_s}, response_block: block_given? ? block.call : default_streamer )
50
+ file.close
51
+ response
52
+ end
21
53
 
22
- ## Converts Ruby Hash into query parameters
23
- ## In general, the format is key=value
24
- ## If value is another Hash, it should keep a json syntax {key:value}
25
- def hash_to_params h
26
- p = []
27
- h.delete_if{ | k, v | k.to_s == "skip_validation" }.each { |k,v| p.push( v.is_a?(Hash) ? "#{k}=#{v.to_json}" : "#{k}=#{v}") }
28
- p.join("&").gsub(" ","")
29
- end
54
+ ##
55
+ # Encodes the authentication parameters.
56
+ #
57
+ # @param authentication [Hash]: Parameters to be encoded.
58
+ def auth_encoder(authentication)
59
+ Base64.urlsafe_encode64(authentication.to_json.to_s).chomp
60
+ end
30
61
 
31
- def build_path path, params = {}
32
- p = path.is_a?(Array) ? ([base_path] << path).join("/") : path # TODO: this line to be removed?
33
- params.size > 0 ? [p, hash_to_params(params)].join("?") : p
34
- end
62
+ ##
63
+ # Validates a Hash object comparing its keys with a given Array of permitted values. Raise an error if the validation fail.
64
+ #
65
+ # @param error [Error]: Error to be raised of the validation fail.
66
+ # @param permitted [Array]: List of permitted keys.
67
+ # @param params [Hash]: Hash object to be validated.
68
+ def validate error, permitted, params
69
+ return if params[:skip_validation]
70
+ unpermitted = params.keys.map(&:to_s) - permitted.map(&:to_s)
71
+ raise error.new(permitted, unpermitted) if unpermitted.size > 0
72
+ end
73
+
74
+ ##
75
+ # Converts Ruby Hash into URL query parameters.
76
+ #
77
+ # In general, query parameters' format is "key=value", but if "value" is another Hash, it should change to a json syntax {key:value}.
78
+ #
79
+ # @param hash [Hash]: Hash object to be converted in a query parameter-like string.
80
+ def hash_to_params hash
81
+ p = []
82
+ hash.delete_if{ | k, v | k.to_s == "skip_validation" }.each { |k,v| p.push( v.is_a?(Hash) ? "#{k}=#{v.to_json}" : "#{k}=#{v}") }
83
+ p.join("&").gsub(" ","")
84
+ end
35
85
 
86
+ ##
87
+ # Builds an URL string using the base path and a set of parameters.
88
+ #
89
+ # @param path [String]: Base URL string.
90
+ # @param hash [Hash]: Hash object to be appended to the URL as query parameters.
91
+ def build_path path, params = {}
92
+ params.size > 0 ? [path, hash_to_params(params)].join("?") : path
93
+ end
94
+
95
+ ##
96
+ # Sets the validation to happen automatically when method parameters include "params" or "body".
97
+ def set_automated_validation
98
+ (self.methods - Object.methods).each do |method|
99
+ params_index = method(method).parameters.map{|ar| ar[1]}.index(:params)
100
+ body_index = method(method).parameters.map{|ar| ar[1]}.index(:body)
101
+
102
+ define_singleton_method(method) do |*args, &block|
103
+ validate Docker::API::InvalidParameter, Docker::API::VALID_PARAMS["#{self.class.name}"]["#{method}"], (args[params_index] || {}) if params_index
104
+ validate Docker::API::InvalidRequestBody, Docker::API::VALID_BODY["#{self.class.name}"]["#{method}"], (args[body_index] || {}) if body_index
105
+ super(*args,&block)
106
+ end
36
107
  end
37
108
  end
109
+
38
110
  end
@@ -13,7 +13,6 @@ class Docker::API::Config < Docker::API::Base
13
13
  #
14
14
  # @param params [Hash]: Parameters that are appended to the URL.
15
15
  def list params = {}
16
- validate Docker::API::InvalidParameter, [:filters], params
17
16
  @connection.get(build_path("/configs",params))
18
17
  end
19
18
 
@@ -25,7 +24,6 @@ class Docker::API::Config < Docker::API::Base
25
24
  #
26
25
  # @param body [Hash]: Request body to be sent as json.
27
26
  def create body = {}
28
- validate Docker::API::InvalidRequestBody, [:Name, :Labels, :Data, :Templating], body
29
27
  @connection.request(method: :post, path: "/configs/create", headers: {"Content-Type": "application/json"}, body: body.to_json)
30
28
  end
31
29
 
@@ -52,8 +50,6 @@ class Docker::API::Config < Docker::API::Base
52
50
  #
53
51
  # @param body [Hash]: Request body to be sent as json.
54
52
  def update name, params = {}, body = {}
55
- validate Docker::API::InvalidParameter, [:version], params
56
- validate Docker::API::InvalidRequestBody, [:Name, :Labels, :Data, :Driver, :Templating], body
57
53
  @connection.request(method: :post, path: build_path("/configs/#{name}/update",params), headers: {"Content-Type": "application/json"}, body: body.to_json)
58
54
  end
59
55
 
@@ -1,20 +1,26 @@
1
- module Docker
2
- module API
3
- class Connection
4
- [:get, :post, :head, :delete, :put].each do | method |
5
- define_method(method) { | path | self.request(method: method, path: path) }
6
- end
7
-
8
- def request params
9
- Docker::API::Response.new(@connection.request(params).data)
10
- end
11
-
12
- def initialize url = nil, params = nil
13
- url ||= 'unix:///'
14
- params ||= url == 'unix:///' ? {socket: '/var/run/docker.sock'} : {}
15
- @connection = Excon.new(url, params)
16
- end
1
+ ##
2
+ # Connection class.
3
+ class Docker::API::Connection
4
+ [:get, :post, :head, :delete, :put].each do | method |
5
+ define_method(method) { | path | self.request(method: method, path: path) }
6
+ end
17
7
 
18
- end
8
+ ##
9
+ # Calls an Excon request and returns a Docker::API::Response object.
10
+ #
11
+ # @param params [Hash]: Request parameters.
12
+ def request params
13
+ Docker::API::Response.new(@connection.request(params).data)
19
14
  end
15
+
16
+ ##
17
+ # Creates an Excon connection.
18
+ #
19
+ # @param url [String]: URL for the connection.
20
+ # @param params [String]: Additional parameters.
21
+ def initialize url = nil, params = nil
22
+ return @connection = Excon.new('unix:///', {socket: '/var/run/docker.sock'}) unless url
23
+ @connection = Excon.new(url, params || {})
24
+ end
25
+
20
26
  end