dockerapi 0.12.0 → 0.17.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: a32e488d06a0afd653bb04ab0ad5131fa8e898973128d7a6661f3d3fa4eae53d
4
- data.tar.gz: 641ffcc096f798fbfff057fb1eecc7ce97ad9191c2acf49f5e97c90bf5ceddc5
3
+ metadata.gz: 1965ae78342ecc9d450e4cc8262352405784881e31231d700dd606a15d9b58eb
4
+ data.tar.gz: bea7418501d8a3c08ea73f6c6970b08afe7358c7a15e790b7d51011bb69cd721
5
5
  SHA512:
6
- metadata.gz: 6cda72170483e133b467a399d77fbcc7668793726b8f67beb4235c5eaf74e2d91977c9544f93ee7d3f3c4b681004d9415f939d2d521aa70151d3a580fc15fc86
7
- data.tar.gz: d45997041c9d706d2c2d0e2c5e3f5ccaedad51d71cb27ba8538898565e6259e30d7ff11ffa60a5dee9ffca3611ed51ddc96ca68af2a5aff490715b4645297c0d
6
+ metadata.gz: 91a6a4e8f85632f9294a07ae2e4bee24d4ff79543b1f50d240638b98d5e9bcc792193be15fa6003d97c73ec8f4b5126f0fe7294367160fce16f8eebd689b5198
7
+ data.tar.gz: 8a9a1b6ee4bbe7f10c0ae1396eb51e2cb246a37f490758a0278dfe7b06612870a4c12886caf01b9a575b255decec7faf5f0f4ef9d49e2df76a3cb80e4ca06776
@@ -1,3 +1,43 @@
1
+ # 0.17.0
2
+
3
+ New block execution introduced in [PR#1](https://github.com/nu12/dockerapi/pull/1).
4
+
5
+ # 0.16.0
6
+
7
+ `Docker::API::Task#logs` method can now receive a block to replace standard output to stdout behavior.
8
+
9
+ Add `auth_encoder` to provide standard implementation for the authentication header where needed.
10
+
11
+ # 0.15.0
12
+
13
+ `Docker::API::System#events` and `Docker::API::Exec#start` methods can now receive a block to replace standard output to stdout behavior.
14
+
15
+ General refactoring and API documentation.
16
+
17
+ # 0.14.0
18
+
19
+ Method `Docker::API::Container#archive` is splitted in `#get_archive` and `#put_archive` as per Docker API documentation.
20
+
21
+ The following `Docker::API::Container` methods that can now receive a block:
22
+ * logs (output to stdout)
23
+ * attach (output to stdout)
24
+ * stats (output to stdout)
25
+ * export (write file)
26
+ * get_archive (write file)
27
+
28
+ # 0.13.0
29
+
30
+ Add default behavior for file read, write and output to stdout. Whenever a method can receive a block, this default behavior can be replaced.
31
+
32
+ The following `Docker::API::Image` methods that can now receive a block:
33
+ * export (write file)
34
+ * create (output to stdout)
35
+ * build (output to stdout)
36
+
37
+ Default output to stdout can be supressed by setting `Docker::API::PRINT_TO_STDOUT` to `false`
38
+
39
+ Method parameters `params` and `body` will be automatically evaluated whenever they are present in the method's signature.
40
+
1
41
  # 0.12.0
2
42
 
3
43
  Add `Docker::API::Plugin` methods:
@@ -1,14 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dockerapi (0.12.0)
5
- excon (~> 0.74.0)
4
+ dockerapi (0.17.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,30 @@
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
+ * [Blocks](#blocks)
25
+ * [Development](#development)
26
+ * [Contributing](#contributing)
27
+ * [License](#license)
4
28
 
5
29
  ## Installation
6
30
 
@@ -8,6 +32,8 @@ Add this line to your application's Gemfile:
8
32
 
9
33
  ```ruby
10
34
  gem 'dockerapi'
35
+ # or
36
+ gem 'dockerapi', github: 'nu12/dockerapi'
11
37
  ```
12
38
 
13
39
  And then execute:
@@ -20,6 +46,12 @@ Or install it yourself as:
20
46
 
21
47
  ## Usage
22
48
 
49
+ The following section will bring you up to speed in order to use most this gem resources with pratical examples.
50
+
51
+ 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/).
52
+
53
+ For a more detailed and comprehensive documentation about this gem's API, please see the [documentation page](https://rubydoc.info/gems/dockerapi).
54
+
23
55
  ### Images
24
56
 
25
57
  ```ruby
@@ -75,13 +107,16 @@ image.prune(filters: {dangling: {"false": true}})
75
107
  image.commit(container: container, repo: "my/image", tag: "latest", comment: "Comment from commit", author: "dockerapi", pause: false )
76
108
 
77
109
  # Build image from a local tar file
78
- image.build("/path/to/file.tar")
110
+ image.build("/path/to/file.tar", {t: "tag"})
111
+
112
+ # Build image using private repository
113
+ image.build("/path/to/file.tar", {t: "tag"}, {"https://index.docker.io/v1/" => {username: "janedoe", password: "janedoe"}})
79
114
 
80
115
  # Build image from a remote tar file
81
- image.build(nil, remote: "https://url.to/file.tar")
116
+ image.build(nil, {remote: "https://url.to/file.tar", t: "tag"})
82
117
 
83
118
  # Build image from a remote Dockerfile
84
- image.build(nil, remote: "https://url.to/Dockerfile")
119
+ image.build(nil, {remote: "https://url.to/Dockerfile", t: "tag"})
85
120
 
86
121
  # Delete builder cache
87
122
  image.delete_cache
@@ -148,7 +183,10 @@ container.stats("nginx", stream: true)
148
183
  container.export("nginx", "~/exported_container")
149
184
 
150
185
  # Get files from container
151
- container.archive("nginx", "~/html.tar", path: "/usr/share/nginx/html/")
186
+ container.get_archive("nginx", "~/html.tar", path: "/usr/share/nginx/html/")
187
+
188
+ # Send files to container
189
+ container.put_archive("nginx", "~/html.tar", path: "/usr/share/nginx/html/")
152
190
 
153
191
  # Stop container
154
192
  container.stop("nginx")
@@ -496,31 +534,38 @@ response.success?
496
534
 
497
535
  To completely skip the validation process, add `:skip_validation => true` in the hash to be validated.
498
536
 
537
+ ### Blocks
538
+
539
+ Some methods can receive a block to alter the default execution:
540
+ * Docker::API::Container#logs
541
+ * Docker::API::Container#attach
542
+ * Docker::API::Container#stats
543
+ * Docker::API::Container#export
544
+ * Docker::API::Container#get_archive
545
+ * Docker::API::Image#create
546
+ * Docker::API::Image#build
547
+ * Docker::API::Image#export
548
+ * Docker::API::System#event
549
+ * Docker::API::Exec#start
550
+ * Docker::API::Task#logs
551
+
552
+ Example:
553
+ ```ruby
554
+ => image = Docker::API::Image.new
555
+
556
+ => image.create(fromImage: "nginx:alpine") do | chunk, bytes_remaining, bytes_total |
557
+ p chunk.to_s
558
+ end
559
+ ```
560
+
561
+ The default blocks can be found in `Docker::API::Base`.
562
+
499
563
  ## Development
500
564
 
501
565
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
502
566
 
503
567
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
504
568
 
505
- ### Road to 1.0.0
506
-
507
- | Class | Tests | Implementation | Refactoring |
508
- |---|---|---|---|
509
- | Image | Ok | Ok | 8/7 |
510
- | Container | Ok | Ok | 8/14 |
511
- | Volume | Ok | Ok | 8/21 |
512
- | Network | Ok | Ok | 8/21 |
513
- | System | Ok | Ok | 8/21 |
514
- | Exec | Ok | Ok | 8/21 |
515
- | Swarm | Ok | Ok | 8/28 |
516
- | Node | Ok | Ok | 8/28 |
517
- | Service | Ok | Ok | 8/28 |
518
- | Task | Ok | Ok | 9/4 |
519
- | Secret | Ok | Ok | 9/4 |
520
- | Config | Ok | Ok | 9/4 |
521
- | Distribution | Ok | Ok | 9/4 |
522
- | Plugin | Ok | 7/24 | 9/4 |
523
-
524
569
  ## Contributing
525
570
 
526
571
  Bug reports and pull requests are welcome on GitHub at https://github.com/nu12/dockerapi.
@@ -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 : 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