dockerapi 0.10.0 → 0.15.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
2
  SHA256:
3
- metadata.gz: aeb3c1971c26c62d0737576e5ec79f2abcf536b1148be5272be8f501dfcae852
4
- data.tar.gz: 1392073ca52d6fecfc12e642368713c2fa44a9ebbcd7629de5fb54faf9ac7209
3
+ metadata.gz: a07cc3ef52a91afb13ab99c130cb6cbed118055aba264df3e0fb0a1ec701ef6d
4
+ data.tar.gz: d9e6e03672a7a47de2cb0fb840569c45582075be679d21995192247633d58d70
5
5
  SHA512:
6
- metadata.gz: 3b03b8e5ce6d95f19c8dd6d357277a102fcc170b35ac989cd080db27c66efcad63125aaedab1c971a8ed435bed7c7447979d332a1b7f43686a2217907bf21fe8
7
- data.tar.gz: 62cd2888ad859834cf949a6189f6e863e1b2f23ce9849fce4a39a1248cfa74efeaff5e0e6220a165d6b7980445a7773dc4bc3f8d4a678fc364a06b205fc07630
6
+ metadata.gz: 46bbd5e8c6cbb41e13b3830aab5ca8825d37a1c85401dedc33aeba3352657f8410e99c8c321bc5e5d10e9eeac6435769f9b7d7570a8910b7f0d0779a3308381a
7
+ data.tar.gz: 672a71377c73a0c0a09796d84afebf2cfe03f3a6182626119c3370ab41112249d881152f1dadbe24ba31775475b4463df5d8c42ca2e9f7d6915c080149fab7ab
@@ -1,3 +1,72 @@
1
+ # 0.15.0
2
+
3
+ `Docker::API::System#events` and `Docker::API::Exec#start` methods that can now receive a block to replace standard output to stdout behavior.
4
+
5
+ General refactoring and API documentation.
6
+
7
+ # 0.14.0
8
+
9
+ Method `Docker::API::Container#archive` is splitted in `#get_archive` and `#put_archive` as per Docker API documentation.
10
+
11
+ The following `Docker::API::Container` methods that can now receive a block:
12
+ * logs (output to stdout)
13
+ * attach (output to stdout)
14
+ * stats (output to stdout)
15
+ * export (write file)
16
+ * get_archive (write file)
17
+
18
+ # 0.13.0
19
+
20
+ Add default behavior for file read, write and output to stdout. Whenever a method can receive a block, this default behavior can be replaced.
21
+
22
+ The following `Docker::API::Image` methods that can now receive a block:
23
+ * export (write file)
24
+ * create (output to stdout)
25
+ * build (output to stdout)
26
+
27
+ Default output to stdout can be supressed by setting `Docker::API::PRINT_TO_STDOUT` to `false`
28
+
29
+ Method parameters `params` and `body` will be automatically evaluated whenever they are present in the method's signature.
30
+
31
+ # 0.12.0
32
+
33
+ Add `Docker::API::Plugin` methods:
34
+ * list
35
+ * privileges
36
+ * install
37
+ * details
38
+ * remove
39
+ * enable
40
+ * disable
41
+ * upgrade
42
+ * create
43
+ * push
44
+ * configure
45
+
46
+ # 0.11.0
47
+
48
+ Add `Docker::API::Task` methods:
49
+ * list
50
+ * details
51
+ * logs
52
+
53
+ Add `Docker::API::Secret` methods:
54
+ * create
55
+ * update
56
+ * list
57
+ * details
58
+ * delete
59
+
60
+ Add `Docker::API::Config` methods:
61
+ * create
62
+ * update
63
+ * list
64
+ * details
65
+ * delete
66
+
67
+ Add `Docker::API::Image` methods:
68
+ * distribution
69
+
1
70
  # 0.10.0
2
71
 
3
72
  Add `Docker::API::Service` methods:
@@ -1,14 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dockerapi (0.10.0)
5
- excon (~> 0.74.0)
4
+ dockerapi (0.15.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
 
@@ -20,6 +43,12 @@ Or install it yourself as:
20
43
 
21
44
  ## Usage
22
45
 
46
+ The following section will bring you up to speed in order to use most this gem resources with pratical examples.
47
+
48
+ 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/).
49
+
50
+ For a more detailed and comprehensive documentation about this gem's API, please see the [documentation page](https://rubydoc.info/gems/dockerapi).
51
+
23
52
  ### Images
24
53
 
25
54
  ```ruby
@@ -44,6 +73,9 @@ image.list
44
73
  # Inspect image
45
74
  image.details("image")
46
75
 
76
+ # Return image digest and platform information by contacting the registry.
77
+ image.distribution("image")
78
+
47
79
  # History
48
80
  image.history("image")
49
81
 
@@ -72,13 +104,16 @@ image.prune(filters: {dangling: {"false": true}})
72
104
  image.commit(container: container, repo: "my/image", tag: "latest", comment: "Comment from commit", author: "dockerapi", pause: false )
73
105
 
74
106
  # Build image from a local tar file
75
- image.build("/path/to/file.tar")
107
+ image.build("/path/to/file.tar", {t: "tag"})
108
+
109
+ # Build image using private repository
110
+ image.build("/path/to/file.tar", {t: "tag"}, {"https://index.docker.io/v1/" => {username: "janedoe", password: "janedoe"}})
76
111
 
77
112
  # Build image from a remote tar file
78
- image.build(nil, remote: "https://url.to/file.tar")
113
+ image.build(nil, {remote: "https://url.to/file.tar", t: "tag"})
79
114
 
80
115
  # Build image from a remote Dockerfile
81
- image.build(nil, remote: "https://url.to/Dockerfile")
116
+ image.build(nil, {remote: "https://url.to/Dockerfile", t: "tag"})
82
117
 
83
118
  # Delete builder cache
84
119
  image.delete_cache
@@ -145,7 +180,10 @@ container.stats("nginx", stream: true)
145
180
  container.export("nginx", "~/exported_container")
146
181
 
147
182
  # Get files from container
148
- container.archive("nginx", "~/html.tar", path: "/usr/share/nginx/html/")
183
+ container.get_archive("nginx", "~/html.tar", path: "/usr/share/nginx/html/")
184
+
185
+ # Send files to container
186
+ container.put_archive("nginx", "~/html.tar", path: "/usr/share/nginx/html/")
149
187
 
150
188
  # Stop container
151
189
  container.stop("nginx")
@@ -325,12 +363,113 @@ service.details("nginx-service")
325
363
 
326
364
  # Delete service
327
365
  service.delete("nginx-service")
366
+ ```
367
+
368
+ ### Task
369
+ ```ruby
370
+ # Connect to local task endpoints
371
+ task = Docker::API::Task.new
372
+
373
+ # List tasks
374
+ task.list
375
+
376
+ # View task logs
377
+ task.logs("task-id", stdout: true)
378
+
379
+ # Inspect service
380
+ task.details("task-id")
381
+ ```
382
+
383
+ ### Secret
384
+ ```ruby
385
+ # Connect to local secret endpoints
386
+ secret = Docker::API::Secret.new
387
+
388
+ # List secrets
389
+ secret.list
390
+
391
+ # Create a secret
392
+ secret.create({Name: "secret-name", Data: "VEhJUyBJUyBOT1QgQSBSRUFMIENFUlRJRklDQVRFCg=="})
393
+
394
+ # Inspect secrets
395
+ secret.details("secret-name")
396
+
397
+ # Update a secret (needs version and current Spec)
398
+ version = secret.details( "secret-name" ).json["Version"]["Index"]
399
+ spec = secret.details("secret-name").json["Spec"]
400
+ secret.update("secret-name", {version: version}, spec.merge!({ Data: "VEhJUyBJUyBOT1QgQSBSRUFMIENFUlRJRklDQVRFCg==" }))
401
+
402
+ # Delete secret
403
+ secret.delete("secret-name")
404
+ ```
405
+
406
+ ### Config
407
+ ```ruby
408
+ # Connect to local config endpoints
409
+ config = Docker::API::Config.new
410
+
411
+ # List configs
412
+ config.list
413
+
414
+ # Create a config
415
+ config.create({Name: "config-name", Data: "VEhJUyBJUyBOT1QgQSBSRUFMIENFUlRJRklDQVRFCg=="})
416
+
417
+ # Inspect configs
418
+ config.details("config-name")
419
+
420
+ # Update a configs (needs version and current Spec)
421
+ version = config.details( "config-name" ).json["Version"]["Index"]
422
+ spec = config.details("config-name").json["Spec"]
423
+ config.update("config-name", {version: version}, spec.merge!({ Data: "VEhJUyBJUyBOT1QgQSBSRUFMIENFUlRJRklDQVRFCg==" }))
424
+
425
+ # Delete config
426
+ config.delete("config-name")
427
+ ```
428
+
429
+ ### Plugin
430
+ ```ruby
431
+ # Connect to local plugin endpoints
432
+ plugin = Docker::API::Plugin.new
433
+
434
+ # List plugins
435
+ plugin.list
436
+
437
+ # List plugin's privileges
438
+ plugin.privileges(remote: "plugin-name")
439
+
440
+ # Install plugin (using defined privileges)
441
+ privileges = plugin.privileges(remote: "plugin-name")
442
+ plugin.install({remote: "plugin-name"}, privileges)
443
+
444
+ # Upgrade plugin (using defined privileges)
445
+ privileges = plugin.privileges(remote: "plugin-name2")
446
+ plugin.upgrade("plugin-name", {remote: "plugin-name2"}, privileges)
447
+
448
+ # Enable plugin
449
+ plugin.enable("plugin-name", timeout: 0)
450
+
451
+ # Disable plugin
452
+ plugin.disable("plugin-name")
453
+
454
+ # Configure plugin
455
+ plugin.configure("plugin-name", ["DEBUG=1"])
456
+
457
+ # Inspect plugin
458
+ plugin.details("plugin-name")
459
+
460
+ # Remove plugin
461
+ plugin.remove("plugin-name")
462
+
463
+ # Create plugin (tar file must contain rootfs folder and config.json file)
464
+ plugin.create("name", "/path/to/file.tar")
328
465
 
466
+ # Push plugin
467
+ plugin.push("name")
329
468
  ```
330
469
 
331
470
  ### Connection
332
471
 
333
- 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.
472
+ 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.
334
473
 
335
474
  ```ruby
336
475
  # Setting different connections
@@ -402,20 +541,22 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
402
541
 
403
542
  | Class | Tests | Implementation | Refactoring |
404
543
  |---|---|---|---|
405
- | Image | Ok | Ok | 8/7 |
406
- | Container | Ok | Ok | 8/14 |
407
- | Volume | Ok | Ok | 8/21 |
408
- | Network | Ok | Ok | 8/21 |
409
- | System | Ok | Ok | 8/21 |
410
- | Exec | Ok | Ok | 8/21 |
411
- | Swarm | Ok | Ok | 8/28 |
412
- | Node | Ok | Ok | 8/28 |
413
- | Service | 7/17 | 7/17 | 8/28 |
414
- | Task | 7/17 | 7/17 | 9/4 |
415
- | Secret | 7/17 | 7/17 | 9/4 |
416
- | Config | 7/17 | 7/17 | 9/4 |
417
- | Distribution | 7/17 | 7/17 | 9/4 |
418
- | Plugin | 7/24 | 7/24 | 9/4 |
544
+ | Image | Ok | Ok | Ok |
545
+ | Container | Ok | Ok | Ok |
546
+ | Volume | Ok | Ok | Ok |
547
+ | Network | Ok | Ok | Ok |
548
+ | System | Ok | Ok | Ok |
549
+ | Exec | Ok | Ok | Ok |
550
+ | Swarm | Ok | Ok | 8/11 |
551
+ | Node | Ok | Ok | 8/11 |
552
+ | Service | Ok | Ok | 8/11 |
553
+ | Task | Ok | Ok | 8/11 |
554
+ | Secret | Ok | Ok | 8/11 |
555
+ | Config | Ok | Ok | 8/14 |
556
+ | Distribution | Ok | Ok | 8/14 |
557
+ | Plugin | Ok | Ok | 8/14 |
558
+
559
+ Add doc in these files: `base`, `connection`, `error`, `response`, `dockerapi`
419
560
 
420
561
  ## Contributing
421
562
 
@@ -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,66 @@
1
- module Docker
2
- module API
3
- class Base
1
+ class Docker::API::Base
2
+
4
3
 
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
4
+ def initialize connection = nil
5
+ raise Docker::API::Error.new("Expected connection to be a Docker::API::Connection class") if connection != nil && !connection.is_a?(Docker::API::Connection)
6
+ @connection = connection || Docker::API::Connection.new
7
+
8
+ (self.methods - Object.methods).each do |method|
9
+ params_index = method(method).parameters.map{|ar| ar[1]}.index(:params)
10
+ body_index = method(method).parameters.map{|ar| ar[1]}.index(:body)
11
11
 
12
- def base_path # TODO: this method to be removed?
13
- "/"
12
+ define_singleton_method(method) do |*args, &block|
13
+ validate Docker::API::InvalidParameter, Docker::API::VALID_PARAMS["#{self.class.name}"]["#{method}"], (args[params_index] || {}) if params_index
14
+ validate Docker::API::InvalidRequestBody, Docker::API::VALID_BODY["#{self.class.name}"]["#{method}"], (args[body_index] || {}) if body_index
15
+ super(*args,&block)
14
16
  end
17
+ end
18
+ end
19
+
20
+ private
15
21
 
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
22
+ def default_streamer
23
+ streamer = lambda do |chunk, remaining_bytes, total_bytes|
24
+ p chunk.to_s.encode('UTF-8', invalid: :replace, undef: :replace, replace: '?') if Docker::API::PRINT_TO_STDOUT
25
+ end
26
+ streamer
27
+ end
21
28
 
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
29
+ def default_writer path
30
+ streamer = lambda do |chunk, remaining_bytes, total_bytes|
31
+ return if "#{chunk}".match(/(No such image)/)
32
+ file = File.open(File.expand_path(path), "wb+")
33
+ file.write(chunk)
34
+ file.close
35
+ end
36
+ streamer
37
+ end
30
38
 
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
39
+ def default_reader path, url, header = {"Content-Type" => "application/x-tar"}, &block
40
+ file = File.open(File.expand_path(path), "r")
41
+ 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 )
42
+ file.close
43
+ response
44
+ end
35
45
 
36
- end
46
+ def validate error, permitted, params
47
+ return if params[:skip_validation]
48
+ unpermitted = params.keys.map(&:to_s) - permitted.map(&:to_s)
49
+ raise error.new(permitted, unpermitted) if unpermitted.size > 0
50
+ end
51
+
52
+ ## Converts Ruby Hash into query parameters
53
+ ## In general, the format is key=value
54
+ ## If value is another Hash, it should keep a json syntax {key:value}
55
+ def hash_to_params h
56
+ p = []
57
+ 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}") }
58
+ p.join("&").gsub(" ","")
59
+ end
60
+
61
+ def build_path path, params = {}
62
+ p = path.is_a?(Array) ? ([base_path] << path).join("/") : path # TODO: this line to be removed?
63
+ params.size > 0 ? [p, hash_to_params(params)].join("?") : p
37
64
  end
65
+
38
66
  end