Skip to content

Commit

Permalink
Specify Docker API version (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
nu12 authored Nov 5, 2024
1 parent f2eabb4 commit 9f6c1ba
Show file tree
Hide file tree
Showing 14 changed files with 72 additions and 61 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
name: CD
on:
push:
branches: [ main ]
tags:
- 'v*.*.*'

jobs:
release:
Expand All @@ -12,9 +13,9 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@21351ecc0a7c196081abca5dc55b08f085efe09a
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6
ruby-version: 3.3
- name: Setup to RubyGems
run: |
mkdir -p $HOME/.gem
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Set up Ruby
uses: ruby/setup-ruby@21351ecc0a7c196081abca5dc55b08f085efe09a
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6
ruby-version: 3.3
- name: Install Docker
run: curl https://get.docker.com | sh
- name: Install dependencies
Expand Down
31 changes: 16 additions & 15 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
PATH
remote: .
specs:
dockerapi (0.19.0)
dockerapi (0.20.0)
excon (~> 0.79)

GEM
remote: https://rubygems.org/
specs:
diff-lcs (1.3)
excon (0.79.0)
diff-lcs (1.5.1)
excon (0.112.0)
rake (12.3.3)
rspec (3.9.0)
rspec-core (~> 3.9.0)
rspec-expectations (~> 3.9.0)
rspec-mocks (~> 3.9.0)
rspec-core (3.9.2)
rspec-support (~> 3.9.3)
rspec-expectations (3.9.2)
rspec (3.13.0)
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
rspec-mocks (~> 3.13.0)
rspec-core (3.13.2)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-mocks (3.9.1)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-support (3.9.3)
rspec-support (~> 3.13.0)
rspec-support (3.13.1)

PLATFORMS
arm64-darwin-23
ruby

DEPENDENCIES
Expand All @@ -33,4 +34,4 @@ DEPENDENCIES
rspec (~> 3.0)

BUNDLED WITH
2.1.4
2.5.11
1 change: 1 addition & 0 deletions lib/docker/api/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ def hash_to_params hash
# @param path [String]: Base URL string.
# @param hash [Hash]: Hash object to be appended to the URL as query parameters.
def build_path path, params = {}
path = "/v#{Docker::API::API_VERSION}#{path}"
params.size > 0 ? [path, hash_to_params(params)].join("?") : path
end

Expand Down
8 changes: 4 additions & 4 deletions lib/docker/api/network.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def details name, params = {}
#
# @param body [Hash]: Request body to be sent as json.
def create body = {}
@connection.request(method: :post, path: "/networks/create", headers: {"Content-Type": "application/json"}, body: body.to_json)
@connection.request(method: :post, path: build_path("/networks/create"), headers: {"Content-Type": "application/json"}, body: body.to_json)
end

##
Expand All @@ -45,7 +45,7 @@ def create body = {}
#
# @param name [String]: The ID or name of the network.
def remove name
@connection.delete("/networks/#{name}")
@connection.delete(build_path("/networks/#{name}"))
end

##
Expand All @@ -68,7 +68,7 @@ def prune params = {}
# @param name [String]: The ID or name of the network.
# @param body [Hash]: Request body to be sent as json.
def connect name, body = {}
@connection.request(method: :post, path: "/networks/#{name}/connect", headers: {"Content-Type": "application/json"}, body: body.to_json)
@connection.request(method: :post, path: build_path("/networks/#{name}/connect"), headers: {"Content-Type": "application/json"}, body: body.to_json)
end

##
Expand All @@ -80,7 +80,7 @@ def connect name, body = {}
# @param name [String]: The ID or name of the network.
# @param body [Hash]: Request body to be sent as json.
def disconnect name, body = {}
@connection.request(method: :post, path: "/networks/#{name}/disconnect", headers: {"Content-Type": "application/json"}, body: body.to_json)
@connection.request(method: :post, path: build_path("/networks/#{name}/disconnect"), headers: {"Content-Type": "application/json"}, body: body.to_json)
end

end
2 changes: 1 addition & 1 deletion lib/docker/api/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def list params = {}
# @param params [Hash]: Parameters that are appended to the URL.
# @param body [Hash]: Request body to be sent as json.
def update name, params = {}, body = {}
@connection.request(method: :post, path: build_path("nodes/#{name}/update", params), headers: {"Content-Type": "application/json"}, body: body.to_json)
@connection.request(method: :post, path: build_path("/nodes/#{name}/update", params), headers: {"Content-Type": "application/json"}, body: body.to_json)
end

##
Expand Down
6 changes: 3 additions & 3 deletions lib/docker/api/system.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def events params = {}, &block
# Docker API: GET /_ping
# @see https://docs.docker.com/engine/api/v1.40/#operation/SystemPing
def ping
@connection.get("/_ping")
@connection.get(build_path("/_ping"))
end

##
Expand All @@ -41,7 +41,7 @@ def ping
# Docker API: GET /info
# @see https://docs.docker.com/engine/api/v1.40/#operation/SystemInfo
def info
@connection.get("/info")
@connection.get(build_path("/info"))
end

##
Expand All @@ -50,7 +50,7 @@ def info
# Docker API: GET /version
# @see https://docs.docker.com/engine/api/v1.40/#operation/SystemVersion
def version
@connection.get("/version")
@connection.get(build_path("/version"))
end

##
Expand Down
12 changes: 6 additions & 6 deletions spec/endpoints/container_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
end

describe "request path" do
it { expect(subject.list( { all: true, filters: {name: {"#{name}": true}} } ).path).to eq("/containers/json?all=true&filters={\"name\":{\"#{name}\":true}}") }
it { expect(subject.list( { all: true, filters: {exited: {"0": true} } } ).path).to eq("/containers/json?all=true&filters={\"exited\":{\"0\":true}}") }
it { expect(subject.list( { all: true, filters: {status: ["running"] } } ).path).to eq("/containers/json?all=true&filters={\"status\":[\"running\"]}") }
it { expect(subject.list( { all: true, filters: {name: {"#{name}": true}} } ).path).to eq("/v#{Docker::API::API_VERSION}/containers/json?all=true&filters={\"name\":{\"#{name}\":true}}") }
it { expect(subject.list( { all: true, filters: {exited: {"0": true} } } ).path).to eq("/v#{Docker::API::API_VERSION}/containers/json?all=true&filters={\"exited\":{\"0\":true}}") }
it { expect(subject.list( { all: true, filters: {status: ["running"] } } ).path).to eq("/v#{Docker::API::API_VERSION}/containers/json?all=true&filters={\"status\":[\"running\"]}") }
end
end

Expand Down Expand Up @@ -98,7 +98,7 @@
it { expect(subject.start(name).status).to eq(204 )}
it { expect(subject.start("doesn-exist").status).to eq(404 )}
it { expect(subject.start(name, {detachKeys: "ctrl-c"}).status).to eq(204 )}
it { expect(subject.start(name, {detachKeys: "ctrl-c"}).path).to eq("/containers/#{name}/start?detachKeys=ctrl-c" )}
it { expect(subject.start(name, {detachKeys: "ctrl-c"}).path).to eq("/v#{Docker::API::API_VERSION}/containers/#{name}/start?detachKeys=ctrl-c" )}
it { expect{subject.start(name, {invalid_value: "invalid"})}.to raise_error(Docker::API::InvalidParameter )}
it do
subject.start(name)
Expand Down Expand Up @@ -126,7 +126,7 @@
it { expect(subject.kill(name).status).to be(204) }
it { expect(subject.kill("doesn-exist").status).to be(404) }
it { expect(subject.kill(name, {signal: "SIGKILL"}).status).to eq(204) }
it { expect(subject.kill(name, {signal: "SIGKILL"}).path).to eq("/containers/#{name}/kill?signal=SIGKILL") }
it { expect(subject.kill(name, {signal: "SIGKILL"}).path).to eq("/v#{Docker::API::API_VERSION}/containers/#{name}/kill?signal=SIGKILL") }
it { expect{subject.kill(name, {invalid_value: "invalid"})}.to raise_error(Docker::API::InvalidParameter) }
it do
subject.stop(name)
Expand All @@ -139,7 +139,7 @@
it { expect(subject.restart("doesn-exist").status).to be(404) }
it { expect(subject.restart(name, {t: 2}).status).to eq(204) }
it { expect(subject.restart(name, {signal: "SIGINT"}).status).to eq(204) }
it { expect(subject.restart(name, {t: 2}).path).to eq("/containers/#{name}/restart?t=2") }
it { expect(subject.restart(name, {t: 2}).path).to eq("/v#{Docker::API::API_VERSION}/containers/#{name}/restart?t=2") }
it { expect{subject.restart(name, {invalid_value: "invalid"})}.to raise_error(Docker::API::InvalidParameter) }
end

Expand Down
34 changes: 17 additions & 17 deletions spec/endpoints/image_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,16 @@
it { expect(subject.list(all: true, filters: {since: {"#{image}": true}}).status).to eq(200) }
end
describe "request path" do
it { expect(subject.list(all: true).path).to eq("/images/json?all=true") }
it { expect(subject.list(all: true, "shared-size": true).path).to eq("/images/json?all=true&shared-size=true") }
it { expect(subject.list(digests: true).path).to eq("/images/json?digests=true") }
it { expect(subject.list(all: true, digests: true).path).to eq("/images/json?all=true&digests=true") }
it { expect(subject.list(all: true, filters: {dangling: {"true": true}}).path).to eq("/images/json?all=true&filters={\"dangling\":{\"true\":true}}") }
it { expect(subject.list(all: true, filters: {label: {"label-here": true}}).path).to eq("/images/json?all=true&filters={\"label\":{\"label-here\":true}}") }
it { expect(subject.list(all: true, filters: {reference: {"#{image}": true}}).path).to eq("/images/json?all=true&filters={\"reference\":{\"#{image}\":true}}") }
it { expect(subject.list(all: true, filters: {before: {"#{image}": true}}).path).to eq("/images/json?all=true&filters={\"before\":{\"#{image}\":true}}") }
it { expect(subject.list(all: true, filters: {since: {"#{image}": true}}).path).to eq("/images/json?all=true&filters={\"since\":{\"#{image}\":true}}") }
it { expect(subject.list(all: true, invalid: true, skip_validation: true).path).to eq("/images/json?all=true&invalid=true") }
it { expect(subject.list(all: true).path).to eq("/v#{Docker::API::API_VERSION}/images/json?all=true") }
it { expect(subject.list(all: true, "shared-size": true).path).to eq("/v#{Docker::API::API_VERSION}/images/json?all=true&shared-size=true") }
it { expect(subject.list(digests: true).path).to eq("/v#{Docker::API::API_VERSION}/images/json?digests=true") }
it { expect(subject.list(all: true, digests: true).path).to eq("/v#{Docker::API::API_VERSION}/images/json?all=true&digests=true") }
it { expect(subject.list(all: true, filters: {dangling: {"true": true}}).path).to eq("/v#{Docker::API::API_VERSION}/images/json?all=true&filters={\"dangling\":{\"true\":true}}") }
it { expect(subject.list(all: true, filters: {label: {"label-here": true}}).path).to eq("/v#{Docker::API::API_VERSION}/images/json?all=true&filters={\"label\":{\"label-here\":true}}") }
it { expect(subject.list(all: true, filters: {reference: {"#{image}": true}}).path).to eq("/v#{Docker::API::API_VERSION}/images/json?all=true&filters={\"reference\":{\"#{image}\":true}}") }
it { expect(subject.list(all: true, filters: {before: {"#{image}": true}}).path).to eq("/v#{Docker::API::API_VERSION}/images/json?all=true&filters={\"before\":{\"#{image}\":true}}") }
it { expect(subject.list(all: true, filters: {since: {"#{image}": true}}).path).to eq("/v#{Docker::API::API_VERSION}/images/json?all=true&filters={\"since\":{\"#{image}\":true}}") }
it { expect(subject.list(all: true, invalid: true, skip_validation: true).path).to eq("/v#{Docker::API::API_VERSION}/images/json?all=true&invalid=true") }
end
it { expect{subject.list(invalid: "invalid")}.to raise_error(Docker::API::InvalidParameter) }
end
Expand Down Expand Up @@ -159,11 +159,11 @@
it { expect(subject.prune(filters: {label: {"LABEL": true}, dangling: {"1": true}}).status).to eq(200) }
end
describe "request path" do
it { expect(subject.prune(filters: {dangling: {"true": true}}).path).to eq("/images/prune?filters={\"dangling\":{\"true\":true}}") }
it { expect(subject.prune(filters: {dangling: {"1": true}}).path).to eq("/images/prune?filters={\"dangling\":{\"1\":true}}") }
it { expect(subject.prune(filters: {until: {"10m": true}}).path).to eq("/images/prune?filters={\"until\":{\"10m\":true}}") }
it { expect(subject.prune(filters: {label: {"LABEL": true}}).path).to eq("/images/prune?filters={\"label\":{\"LABEL\":true}}") }
it { expect(subject.prune(filters: {label: {"LABEL": true}, dangling: {"1": true}}).path).to eq("/images/prune?filters={\"label\":{\"LABEL\":true},\"dangling\":{\"1\":true}}") }
it { expect(subject.prune(filters: {dangling: {"true": true}}).path).to eq("/v#{Docker::API::API_VERSION}/images/prune?filters={\"dangling\":{\"true\":true}}") }
it { expect(subject.prune(filters: {dangling: {"1": true}}).path).to eq("/v#{Docker::API::API_VERSION}/images/prune?filters={\"dangling\":{\"1\":true}}") }
it { expect(subject.prune(filters: {until: {"10m": true}}).path).to eq("/v#{Docker::API::API_VERSION}/images/prune?filters={\"until\":{\"10m\":true}}") }
it { expect(subject.prune(filters: {label: {"LABEL": true}}).path).to eq("/v#{Docker::API::API_VERSION}/images/prune?filters={\"label\":{\"LABEL\":true}}") }
it { expect(subject.prune(filters: {label: {"LABEL": true}, dangling: {"1": true}}).path).to eq("/v#{Docker::API::API_VERSION}/images/prune?filters={\"label\":{\"LABEL\":true},\"dangling\":{\"1\":true}}") }
end
it { expect{subject.prune( invalid: "invalid")}.to raise_error(Docker::API::InvalidParameter) }
end
Expand All @@ -174,10 +174,10 @@
it { expect(subject.build("resources/build.tar.xz", q: true, rm: false).status).to eq(200) }
it { expect(subject.build("resources/build.tar.xz", memory: 4000000, rm: true, forcerm:true).status).to eq(200) }
it { expect(subject.build("resources/build.tar.xz", memory: 4000000, rm: true, forcerm:true, pull:true).status).to eq(200) }
it { expect(subject.build(nil, remote: "https://github.com/nu12/dockerapi/blob/master/resources/build.tar.xz?raw=true").status).to eq(200) }
it { expect(subject.build(nil, remote: "https://github.com/nu12/dockerapi/raw/refs/heads/main/resources/build.tar.xz").status).to eq(200) }
it { expect(subject.build(nil, remote: "https://raw.githubusercontent.com/nu12/dockerapi/master/resources/Dockerfile").status).to eq(200) }
it { expect{subject.build("resources/build.tar.xz", invalid: "invalid")}.to raise_error(Docker::API::InvalidParameter) }
it { expect{subject.build(nil, remote: "https://github.com/nu12/dockerapi/blob/master/resources/build.tar.xz?raw=true", invalid: "invalid")}.to raise_error(Docker::API::InvalidParameter) }
it { expect{subject.build(nil, remote: "https://github.com/nu12/dockerapi/raw/refs/heads/main/resources/build.tar.xz", invalid: "invalid")}.to raise_error(Docker::API::InvalidParameter) }
it { expect{subject.build(nil, invalid: "invalid", skip_validation: true)}.to raise_error(Docker::API::Error) }
end

Expand Down
2 changes: 1 addition & 1 deletion spec/endpoints/network_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
end

describe ".create" do
it { expect(subject.create.status).to eq(500) }
it { expect(subject.create.status).to eq(400) }
it do
expect(subject.create(
Name: "rspec-network",
Expand Down
2 changes: 1 addition & 1 deletion spec/endpoints/node_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
RSpec.describe Docker::API::Node do
ip_address = Socket.ip_address_list[2].ip_address
ip_address = get_api_ip_address
subject { described_class.new }
it { is_expected.to respond_to(:list) }
it { is_expected.to respond_to(:details) }
Expand Down
4 changes: 2 additions & 2 deletions spec/endpoints/swarm_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require 'socket'

RSpec.describe Docker::API::Swarm do
ip_address = Socket.ip_address_list[2].ip_address
ip_address = get_api_ip_address

subject { described_class.new }
describe ".init" do
Expand Down
12 changes: 6 additions & 6 deletions spec/endpoints/system_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,23 @@
describe ".ping" do
it { expect(subject).to respond_to(:ping) }
it { expect(subject.ping.status).to eq(200) }
it { expect(subject.ping.path).to eq("/_ping") }
it { expect(subject.ping.path).to eq("/v#{Docker::API::API_VERSION}/_ping") }
end

describe ".info" do
it { expect(subject).to respond_to(:info) }
it { expect(subject.info.status).to eq(200) }
it { expect(subject.info.success?).to eq(true) }
it { expect(subject.info.json).to be_kind_of(Hash) }
it { expect(subject.info.path).to eq("/info") }
it { expect(subject.info.path).to eq("/v#{Docker::API::API_VERSION}/info") }
end

describe ".version" do
it { expect(subject).to respond_to(:version) }
it { expect(subject.version.status).to eq(200) }
it { expect(subject.version.success?).to eq(true) }
it { expect(subject.version.json).to be_kind_of(Hash) }
it { expect(subject.version.path).to eq("/version") }
it { expect(subject.version.path).to eq("/v#{Docker::API::API_VERSION}/version") }
end

describe ".events" do
Expand All @@ -35,7 +35,7 @@
it { expect(described_class.new).to respond_to(:events) }
it { expect(subject.status).to eq(200) }
it { expect(subject.success?).to eq(true) }
it { expect(subject.path).to eq("/events?until=#{now}") }
it { expect(subject.path).to eq("/v#{Docker::API::API_VERSION}/events?until=#{now}") }
it { expect{described_class.new.events(invalid: true)}.to raise_error(Docker::API::InvalidParameter) }
it { expect{described_class.new.events(invalid: true, skip_validation: false)}.to raise_error(Docker::API::InvalidParameter) }
end
Expand All @@ -45,9 +45,9 @@
it { expect(subject.df.status).to eq(200) }
it { expect(subject.df.success?).to eq(true) }
it { expect(subject.df.json).to be_kind_of(Hash) }
it { expect(subject.df.path).to eq("/system/df") }
it { expect(subject.df.path).to eq("/v#{Docker::API::API_VERSION}/system/df") }
it { expect{subject.df(invalid: "true")}.to raise_error(Docker::API::InvalidParameter) }
it { expect{subject.df(type: "container")}.not_to raise_error }
it { expect(subject.df(type: "container").path).to eq("/system/df?type=container" )}
it { expect(subject.df(type: "container").path).to eq("/v#{Docker::API::API_VERSION}/system/df?type=container" )}
end
end
8 changes: 8 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,11 @@
c.syntax = :expect
end
end

def get_api_ip_address

Socket.ip_address_list.each do |addr|
return addr.ip_address if addr.ipv4? && !addr.ipv4_loopback? && addr.ip_address =~ /\A\d{1,3}(\.\d{1,3}){3}\z/
end

end

0 comments on commit 9f6c1ba

Please sign in to comment.