dockerapi 0.9.0 → 0.14.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: 2fa69dcb4c7b79c558bc6749b51def3a8a056e39259ad8163c84fec253193c67
4
- data.tar.gz: '0998c5433ddcd3c4bbcc43ea6c21d61220527f7864c524e83bf0b3aedec501fd'
3
+ metadata.gz: ac123f7f5ed500758fd1bb2a9f214495e71c6848517662eae15b92dfa00387aa
4
+ data.tar.gz: 270f7a7e14d43f73c402191f11ebf9233aa8b7e2c2e314ac3eeb2875487c5120
5
5
  SHA512:
6
- metadata.gz: cafcf788d269546dd338daf50247df1ee1cf6af16372b50a2a6404b2323e0f8d6f78384789c245d122855d325e355dd9f822e4c61e5df4fb5bb9c7af79e11cac
7
- data.tar.gz: b63d32250bfa09e067b56b19a2737ffc35e130511cd17dd31ffbb71db494406ff2b9e85e6e7226161e126b4d423a6fd570c3da6695dcb0d18407ce1c9a706190
6
+ metadata.gz: 878a7c0a146bc6657909151ff0e866c1b9cc93f1dc57ed6c7d0e91b87063e41496af294d1f1e7318b11b0ba3eaf03823e5e081b664b4c3bdd326d4298aed6c65
7
+ data.tar.gz: fee3d36fd9de8619fc27c588c1285c9acd6ca20a3a6ce1f9fd2ea67c807c74d90ae1a0b531ec233a227ccfd4655056e0c33e6605fa9a31040f6984ca2e3a6798
@@ -1,3 +1,76 @@
1
+ # 0.14.0
2
+
3
+ Method `Docker::API::Container#archive` is splitted in `#get_archive` and `#put_archive` as per Docker API documentation.
4
+
5
+ The following `Docker::API::Container` methods that can now receive a block:
6
+ * logs (output to stdout)
7
+ * attach (output to stdout)
8
+ * stats (output to stdout)
9
+ * export (write file)
10
+ * get_archive (write file)
11
+
12
+ # 0.13.0
13
+
14
+ Add default behavior for file read, write and output to stdout. Whenever a method can receive a block, this default behavior can be replaced.
15
+
16
+ The following `Docker::API::Image` methods that can now receive a block:
17
+ * export (write file)
18
+ * create (output to stdout)
19
+ * build (output to stdout)
20
+
21
+ Default output to stdout can be supressed by setting `Docker::API::PRINT_TO_STDOUT` to `false`
22
+
23
+ Method parameters `params` and `body` will be automatically evaluated whenever they are present in the method's signature.
24
+
25
+ # 0.12.0
26
+
27
+ Add `Docker::API::Plugin` methods:
28
+ * list
29
+ * privileges
30
+ * install
31
+ * details
32
+ * remove
33
+ * enable
34
+ * disable
35
+ * upgrade
36
+ * create
37
+ * push
38
+ * configure
39
+
40
+ # 0.11.0
41
+
42
+ Add `Docker::API::Task` methods:
43
+ * list
44
+ * details
45
+ * logs
46
+
47
+ Add `Docker::API::Secret` methods:
48
+ * create
49
+ * update
50
+ * list
51
+ * details
52
+ * delete
53
+
54
+ Add `Docker::API::Config` methods:
55
+ * create
56
+ * update
57
+ * list
58
+ * details
59
+ * delete
60
+
61
+ Add `Docker::API::Image` methods:
62
+ * distribution
63
+
64
+ # 0.10.0
65
+
66
+ Add `Docker::API::Service` methods:
67
+ * create
68
+ * update
69
+ * list
70
+ * details
71
+ * logs
72
+ * delete
73
+
1
74
  # 0.9.0
2
75
 
3
76
  Significant change: `#inspect` is now deprecated and replaced by `#details` in the following classes:
@@ -1,14 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dockerapi (0.9.0)
5
- excon (~> 0.74.0)
4
+ dockerapi (0.14.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
@@ -134,7 +169,7 @@ container.top("nginx").json
134
169
  # View filesystem changes
135
170
  container.changes("nginx")
136
171
 
137
- # View filesystem logs
172
+ # View container logs
138
173
  container.logs("nginx", stdout: true)
139
174
  container.logs("nginx", stdout: true, follow: true)
140
175
 
@@ -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")
@@ -297,9 +335,141 @@ node.update("node-id", {version: "version"}, {Role: "manager", Availability: "ac
297
335
  node.delete("node-id")
298
336
  ```
299
337
 
338
+ ### Service
339
+ ```ruby
340
+ # Connect to local service endpoints
341
+ service = Docker::API::Service.new
342
+
343
+ # List services
344
+ service.list
345
+
346
+ # Create a service
347
+ service.create({Name: "nginx-service",
348
+ TaskTemplate: {ContainerSpec: { Image: "nginx:alpine" }},
349
+ Mode: { Replicated: { Replicas: 2 } },
350
+ EndpointSpec: { Ports: [ {Protocol: "tcp", PublishedPort: 80, TargetPort: 80} ] }
351
+ })
352
+
353
+ # Update a service (needs version and current Spec)
354
+ version = service.details( service ).json["Version"]["Index"]
355
+ spec = service.details(service).json["Spec"]
356
+ service.update("nginx-service", {version: version}, spec.merge!({ Mode: { Replicated: { Replicas: 1 } } }))
357
+
358
+ # View service logs
359
+ service.logs("nginx-service", stdout: true)
360
+
361
+ # Inspect service
362
+ service.details("nginx-service")
363
+
364
+ # Delete service
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")
465
+
466
+ # Push plugin
467
+ plugin.push("name")
468
+ ```
469
+
300
470
  ### Connection
301
471
 
302
- 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.
303
473
 
304
474
  ```ruby
305
475
  # Setting different connections
@@ -371,20 +541,22 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
371
541
 
372
542
  | Class | Tests | Implementation | Refactoring |
373
543
  |---|---|---|---|
374
- | Image | Ok | Ok | 8/7 |
375
- | Container | Ok | Ok | 8/14 |
376
- | Volume | Ok | Ok | 8/21 |
377
- | Network | Ok | Ok | 8/21 |
378
- | System | Ok | Ok | 8/21 |
379
- | Exec | Ok | Ok | 8/21 |
380
- | Swarm | Ok | Ok | 8/28 |
381
- | Node | Ok | Ok | 8/28 |
382
- | Service | 7/17 | 7/17 | 8/28 |
383
- | Task | 7/17 | 7/17 | 9/4 |
384
- | Secret | 7/17 | 7/17 | 9/4 |
385
- | Config | 7/17 | 7/17 | 9/4 |
386
- | Distribution | 7/17 | 7/17 | 9/4 |
387
- | Plugin | 7/24 | 7/24 | 9/4 |
544
+ | Image | Ok | Ok | Ok |
545
+ | Container | Ok | Ok | Ok |
546
+ | Volume | Ok | Ok | 8/14 |
547
+ | Network | Ok | Ok | 8/14 |
548
+ | System | Ok | Ok | 8/14 |
549
+ | Exec | Ok | Ok | 8/14 |
550
+ | Swarm | Ok | Ok | 8/21 |
551
+ | Node | Ok | Ok | 8/21 |
552
+ | Service | Ok | Ok | 8/21 |
553
+ | Task | Ok | Ok | 8/28 |
554
+ | Secret | Ok | Ok | 8/28 |
555
+ | Config | Ok | Ok | 8/28 |
556
+ | Distribution | Ok | Ok | 8/28 |
557
+ | Plugin | Ok | Ok | 8/28 |
558
+
559
+ Add doc in these files: `base`, `connection`, `error`, `response`, `dockerapi`
388
560
 
389
561
  ## Contributing
390
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