dockerapi 0.9.0 → 0.14.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: 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