docker-swarm-api 1.2.2 → 1.2.3
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 +4 -4
- data/README.md +42 -77
- data/lib/docker/swarm/network.rb +8 -1
- data/lib/docker/swarm/service.rb +65 -0
- data/lib/docker/swarm/swarm.rb +93 -86
- data/lib/docker/swarm/task.rb +16 -0
- data/lib/docker/swarm/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f231ed6bde66591fce70f5c3c5d653d3c21abd52
|
4
|
+
data.tar.gz: e33c69b6e3ad5a10a070d9de06f358093413780d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3885fddc8388316922b7a4371d1d10a64084a59fb8d373fd4e2a2df8fd76f241f510ce7bb4d098ed7427c95e2bf9f6702e52092b82372a6d9464a15abe033d52
|
7
|
+
data.tar.gz: 52a89eb4cede7dff51e836db236737711ceccd7e648d13ada96e18f50b5f91f7b18078194d10092306f3e21aa112d546389a81c581974bce888a1327efacbb29
|
data/README.md
CHANGED
@@ -1,120 +1,85 @@
|
|
1
1
|
# docker-swarm-api
|
2
2
|
|
3
|
-
|
3
|
+
Ruby GEM providing API for managing Docker Swarm clusters.
|
4
|
+
|
5
|
+
MIT License
|
4
6
|
|
5
|
-
|
7
|
+
Must use Docker Engine Version of 1.12 or above. Docker Engine version 1.12.5 required to make overlay networks with API.
|
6
8
|
|
7
|
-
|
9
|
+
Must use Docker API Version of 1.24 or above.
|
10
|
+
|
11
|
+
This project leverages swipely/docker-api (https://github.com/swipely/docker-api), and adds Docker Swarm capability.
|
8
12
|
|
9
13
|
Sample Usage
|
10
14
|
------------
|
11
15
|
```ruby
|
12
|
-
#
|
16
|
+
# Make a connection to the Swarm manager's API. (Assumes port 2375 exposed for API)
|
13
17
|
master_connection = Docker::Swarm::Connection.new('http://10.20.30.1:2375')
|
14
18
|
|
15
19
|
# Manager node intializes swarm
|
16
|
-
swarm_init_options = {
|
17
|
-
"ListenAddr" => "0.0.0.0:2377",
|
18
|
-
}
|
20
|
+
swarm_init_options = { "ListenAddr" => "0.0.0.0:2377" }
|
19
21
|
swarm = Docker::Swarm::Swarm.init(swarm_init_options, master_connection)
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
nodes = Docker::Swarm::Node.all({}, master_connection)
|
23
|
+
# Gather all nodes available to swarm (overlay and bridges)
|
24
|
+
nodes = swarm.nodes()
|
24
25
|
expect(nodes.length).to eq 1
|
25
26
|
|
26
27
|
# Worker joins swarm
|
27
28
|
worker_connection = Docker::Swarm::Connection.new('http://10.20.30.2:2375')
|
28
|
-
swarm.
|
29
|
+
swarm.join_worker(worker_connection)
|
30
|
+
|
31
|
+
# Join another manager to the swarm
|
32
|
+
manager_2_connection = Docker::Swarm::Connection.new('http://10.20.30.3:2375')
|
33
|
+
swarm.join_manager(manager_2_connection)
|
29
34
|
|
30
35
|
# Gather all nodes of swarm
|
31
|
-
nodes = swarm.nodes
|
36
|
+
nodes = swarm.nodes()
|
32
37
|
|
33
38
|
# Create a network which connect services
|
34
|
-
network = swarm.
|
39
|
+
network = swarm.create_overlay_network(network_name)
|
35
40
|
|
36
41
|
# Find all networks in swarm cluster
|
37
|
-
networks = swarm.networks
|
42
|
+
networks = swarm.networks()
|
38
43
|
|
39
44
|
# Create a service with 5 replicas
|
40
|
-
service_create_options = {
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
}
|
57
|
-
},
|
58
|
-
"Placement" => {},
|
59
|
-
"Resources" => {
|
60
|
-
"Limits" => {
|
61
|
-
"MemoryBytes" => 104857600
|
62
|
-
},
|
63
|
-
"Reservations" => {
|
64
|
-
}
|
65
|
-
},
|
66
|
-
"RestartPolicy" => {
|
67
|
-
"Condition" => "on-failure",
|
68
|
-
"Delay" => 1,
|
69
|
-
"MaxAttempts" => 3
|
70
|
-
}
|
71
|
-
},
|
72
|
-
"Mode" => {
|
73
|
-
"Replicated" => {
|
74
|
-
"Replicas" => 5
|
75
|
-
}
|
76
|
-
},
|
77
|
-
"UpdateConfig" => {
|
78
|
-
"Delay" => 2,
|
79
|
-
"Parallelism" => 2,
|
80
|
-
"FailureAction" => "pause"
|
81
|
-
},
|
82
|
-
"EndpointSpec" => {
|
83
|
-
"Ports" => [
|
84
|
-
{
|
85
|
-
"Protocol" => "tcp",
|
86
|
-
"PublishedPort" => 80,
|
87
|
-
"TargetPort" => 80
|
88
|
-
}
|
89
|
-
]
|
90
|
-
},
|
91
|
-
"Labels" => {
|
92
|
-
"foo" => "bar"
|
93
|
-
}
|
94
|
-
}
|
95
|
-
|
45
|
+
service_create_options = {"Name"=>"nginx",
|
46
|
+
"TaskTemplate" =>
|
47
|
+
{"ContainerSpec" =>
|
48
|
+
{"Networks" => [], "Image" => "nginx:1.11.7", "Mounts" => [], "User" => "root"},
|
49
|
+
"Env" => ["TEST_ENV=test"],
|
50
|
+
"LogDriver" => {"Name"=>"json-file", "Options"=>{"max-file"=>"3", "max-size"=>"10M"}},
|
51
|
+
"Placement" => {},
|
52
|
+
"Resources" => {"Limits"=>{"MemoryBytes"=>104857600}, "Reservations"=>{}},
|
53
|
+
"RestartPolicy" => {"Condition"=>"on-failure", "Delay"=>1, "MaxAttempts"=>3}},
|
54
|
+
"Mode"=>{"Replicated" => {"Replicas" => 5}},
|
55
|
+
"UpdateConfig" => {"Delay" => 2, "Parallelism" => 2, "FailureAction" => "pause"},
|
56
|
+
"EndpointSpec"=>
|
57
|
+
{"Ports" => [{"Protocol"=>"tcp", "PublishedPort" => 8181, "TargetPort" => 80}]},
|
58
|
+
"Labels" => {"layer" => "database"},
|
59
|
+
"Networks" => [{"Target" => "my-network"}]
|
60
|
+
}
|
96
61
|
service = swarm.create_service(service_create_options)
|
97
62
|
|
98
63
|
# Retrieve all manager nodes of swarm
|
99
|
-
manager_nodes = swarm.manager_nodes
|
64
|
+
manager_nodes = swarm.manager_nodes()
|
100
65
|
|
101
66
|
# Retrieve all worker nodes (that aren't managers)
|
102
|
-
worker_nodes = swarm.worker_nodes
|
67
|
+
worker_nodes = swarm.worker_nodes()
|
103
68
|
|
104
69
|
# Drain a worker node - stop hosting tasks/containers of services
|
105
70
|
worker_node = worker_nodes.first
|
106
|
-
worker_node.drain
|
71
|
+
worker_node.drain()
|
107
72
|
|
108
73
|
# Gather all tasks (containers for service) being hosted by the swarm cluster
|
109
|
-
tasks = swarm.tasks
|
74
|
+
tasks = swarm.tasks()
|
110
75
|
|
111
76
|
# Scale up or down the number of replicas on a service
|
112
77
|
service.scale(20)
|
113
78
|
|
114
79
|
# Worker leaves the swarm - no forcing
|
115
|
-
swarm.leave(
|
80
|
+
swarm.leave(worker_node, node)
|
116
81
|
|
117
|
-
# Manager leaves the swarm - forced because manager
|
118
|
-
swarm.leave(
|
82
|
+
# Manager leaves the swarm - forced because last manager needs to use 'force' to leave the issue.
|
83
|
+
swarm.leave(manager_node, true)
|
119
84
|
|
120
85
|
```
|
data/lib/docker/swarm/network.rb
CHANGED
@@ -20,13 +20,20 @@ class Docker::Swarm::Network
|
|
20
20
|
return @hash['Name']
|
21
21
|
end
|
22
22
|
|
23
|
+
def driver
|
24
|
+
return @hash['Driver']
|
25
|
+
end
|
26
|
+
|
23
27
|
def remove
|
28
|
+
network_name = name
|
24
29
|
response = @swarm.connection.delete("/networks/#{id()}", {}, expects: [200, 204, 500], full_response: true)
|
25
30
|
if (response.status > 204)
|
26
31
|
raise "Error deleting network (#{name}) HTTP-#{response.status} #{response.body}"
|
27
32
|
end
|
33
|
+
while (@swarm.find_network_by_name(network_name) != nil)
|
34
|
+
sleep 1
|
35
|
+
end
|
28
36
|
end
|
29
|
-
|
30
37
|
end
|
31
38
|
|
32
39
|
# EXAMPLE INSPECT OF OVERLAY NETWORK:
|
data/lib/docker/swarm/service.rb
CHANGED
@@ -17,6 +17,12 @@ class Docker::Swarm::Service
|
|
17
17
|
return @hash['ID']
|
18
18
|
end
|
19
19
|
|
20
|
+
def reload()
|
21
|
+
s = @swarm.find_service(id())
|
22
|
+
@hash = s.hash
|
23
|
+
return self
|
24
|
+
end
|
25
|
+
|
20
26
|
def network_ids
|
21
27
|
network_ids = []
|
22
28
|
@hash['Endpoint']['VirtualIPs'].each do |network_info|
|
@@ -41,6 +47,65 @@ class Docker::Swarm::Service
|
|
41
47
|
self.update(@hash['Spec'])
|
42
48
|
end
|
43
49
|
|
50
|
+
|
51
|
+
def self.DEFAULT_OPTIONS
|
52
|
+
default_service_create_options = {
|
53
|
+
"Name" => "<<Required>>",
|
54
|
+
"TaskTemplate" => {
|
55
|
+
"ContainerSpec" => {
|
56
|
+
"Image" => "<<Required>>",
|
57
|
+
"Mounts" => [],
|
58
|
+
"User" => "root"
|
59
|
+
},
|
60
|
+
"Env" => [],
|
61
|
+
"LogDriver" => {
|
62
|
+
"Name" => "json-file",
|
63
|
+
"Options" => {
|
64
|
+
"max-file" => "3",
|
65
|
+
"max-size" => "10M"
|
66
|
+
}
|
67
|
+
},
|
68
|
+
"Placement" => {},
|
69
|
+
"Resources" => {
|
70
|
+
"Limits" => {
|
71
|
+
"MemoryBytes" => 104857600
|
72
|
+
},
|
73
|
+
"Reservations" => {
|
74
|
+
# "NanoCPUs" => ?
|
75
|
+
# MemoryBytes =>
|
76
|
+
}
|
77
|
+
},
|
78
|
+
"RestartPolicy" => {
|
79
|
+
"Condition" => "on-failure",
|
80
|
+
"Delay" => 1,
|
81
|
+
"MaxAttempts" => 3
|
82
|
+
}
|
83
|
+
}, # End of TaskTemplate
|
84
|
+
"Mode" => {
|
85
|
+
"Replicated" => {
|
86
|
+
"Replicas" => 1
|
87
|
+
}
|
88
|
+
},
|
89
|
+
"UpdateConfig" => {
|
90
|
+
"Delay" => 2,
|
91
|
+
"Parallelism" => 2,
|
92
|
+
"FailureAction" => "pause"
|
93
|
+
},
|
94
|
+
"EndpointSpec" => {
|
95
|
+
"Ports" => [
|
96
|
+
{
|
97
|
+
# "Protocol" => "http",
|
98
|
+
# "PublishedPort" => 2881,
|
99
|
+
# "TargetPort" => 2881
|
100
|
+
}
|
101
|
+
]
|
102
|
+
},
|
103
|
+
"Labels" => {
|
104
|
+
"foo" => "bar"
|
105
|
+
}
|
106
|
+
}
|
107
|
+
return default_service_create_options
|
108
|
+
end
|
44
109
|
|
45
110
|
|
46
111
|
end
|
data/lib/docker/swarm/swarm.rb
CHANGED
@@ -9,61 +9,58 @@ class Docker::Swarm::Swarm
|
|
9
9
|
|
10
10
|
def initialize(hash, manager_connection, options = {})
|
11
11
|
@hash = hash
|
12
|
-
# @manager_connection = manager_connection
|
13
12
|
@id = hash['ID']
|
14
13
|
@worker_join_token = hash['JoinTokens']['Worker']
|
15
14
|
@manager_join_token = hash['JoinTokens']['Manager']
|
16
15
|
@node_hash = {}
|
17
16
|
@manager_connection = manager_connection
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
else
|
27
|
-
node.connection = Docker::Swarm::Connection.new("tcp://#{ip_address}:#{docker_port}")
|
28
|
-
end
|
29
|
-
else
|
30
|
-
ip_address = nil
|
31
|
-
begin
|
32
|
-
ip_address = Resolv::DNS.new.getaddress(node.host_name())
|
33
|
-
rescue
|
34
|
-
ip_address = Resolv::Hosts.new.getaddress(node.host_name())
|
35
|
-
if (!ip_address)
|
36
|
-
host_addresses = options[:host_addresses]
|
37
|
-
ip_address = host_addresses[node.host_name]
|
38
|
-
end
|
39
|
-
end
|
40
|
-
node.connection = Docker::Swarm::Connection.new("tcp://#{ip_address}:#{docker_port}")
|
41
|
-
end
|
42
|
-
@node_hash[node.id] = {hash: node.hash, connection: node.connection}
|
43
|
-
|
44
|
-
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def store_manager(manager_connection, listen_address_and_port)
|
20
|
+
node = nodes.find {|n|
|
21
|
+
(n.hash['ManagerStatus']) && (n.hash['ManagerStatus']['Leader'] == true) && (n.hash['ManagerStatus']['Addr'] == listen_address_and_port)
|
22
|
+
}
|
23
|
+
raise "Node not found for: #{listen_address}" if (!node)
|
24
|
+
@node_hash[node.id] = {hash: node.hash, connection: manager_connection}
|
45
25
|
end
|
46
26
|
|
47
|
-
def join(node_connection, join_token)
|
27
|
+
def join(node_connection, join_token = nil, listen_address = "0.0.0.0:2377")
|
28
|
+
join_token = @worker_join_token
|
48
29
|
node_ids_before = nodes().collect {|n| n.id}
|
49
30
|
query = {}
|
50
31
|
master_ip = self.connection.url.split("//").last.split(":").first
|
51
32
|
new_node_ip = node_connection.url.split("//").last.split(":").first
|
33
|
+
|
52
34
|
join_options = {
|
53
|
-
"ListenAddr" => "
|
35
|
+
"ListenAddr" => "#{listen_address}",
|
54
36
|
"AdvertiseAddr" => "#{new_node_ip}:2377",
|
55
37
|
"RemoteAddrs" => ["#{master_ip}:2377"],
|
56
38
|
"JoinToken" => join_token
|
57
39
|
}
|
58
40
|
new_node = nil
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
41
|
+
response = node_connection.post('/swarm/join', query, :body => join_options.to_json, expects: [200, 406, 500], full_response: true)
|
42
|
+
if (response.status == 200)
|
43
|
+
nodes.each do |node|
|
44
|
+
if (!node_ids_before.include? node.id)
|
45
|
+
new_node = node
|
46
|
+
@node_hash[node.id] = {hash: node.hash, connection: node_connection}
|
47
|
+
end
|
64
48
|
end
|
49
|
+
return new_node
|
50
|
+
elsif (response.status == 406)
|
51
|
+
puts "Node is already part of a swarm - maybe this swarm, maybe another swarm."
|
52
|
+
return nil
|
53
|
+
else
|
54
|
+
raise "Error joining (#{node_connection}): HTTP-#{response.status} #{response.body}"
|
65
55
|
end
|
66
|
-
|
56
|
+
end
|
57
|
+
|
58
|
+
def join_worker(node_connection, listen_address = "0.0.0.0:2377")
|
59
|
+
join(node_connection, @worker_join_token)
|
60
|
+
end
|
61
|
+
|
62
|
+
def join_manager(manager_connection, listen_address = "0.0.0.0:2377")
|
63
|
+
join(node_connection, @manager_join_token, listen_address)
|
67
64
|
end
|
68
65
|
|
69
66
|
def connection
|
@@ -76,14 +73,6 @@ class Docker::Swarm::Swarm
|
|
76
73
|
return @manager_connection
|
77
74
|
end
|
78
75
|
|
79
|
-
def join_worker(node_connection)
|
80
|
-
join(node_connection, @worker_join_token)
|
81
|
-
end
|
82
|
-
|
83
|
-
def join_manager(manager_connection)
|
84
|
-
join(node_connection, @manager_join_token)
|
85
|
-
end
|
86
|
-
|
87
76
|
def remove
|
88
77
|
services().each do |service|
|
89
78
|
service.remove()
|
@@ -144,46 +133,54 @@ class Docker::Swarm::Swarm
|
|
144
133
|
return all_networks
|
145
134
|
end
|
146
135
|
|
147
|
-
def create_network(
|
148
|
-
|
136
|
+
def create_network(options)
|
137
|
+
response = connection.post('/networks/create', {}, body: options.to_json, expects: [200, 201, 500], full_response: true)
|
138
|
+
if (response.status <= 201)
|
139
|
+
hash = JSON.parse(response.body)
|
140
|
+
response = connection.get("/networks/#{hash['Id']}", {}, expects: [200, 201], full_response: true)
|
141
|
+
hash = Docker::Util.parse_json(response.body)
|
142
|
+
network = Docker::Swarm::Network.new(self, hash)
|
143
|
+
return network
|
144
|
+
else
|
145
|
+
raise "Error creating network: HTTP-#{response.status} - #{response.body}"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def create_network_overlay(network_name)
|
150
|
+
max_vxlanid = 200
|
151
|
+
networks.each do |network|
|
152
|
+
if (network.driver == 'overlay')
|
153
|
+
if (network.hash['Options'])
|
154
|
+
vxlanid = network.hash['Options']["com.docker.network.driver.overlay.vxlanid_list"]
|
155
|
+
if (vxlanid) && (vxlanid.to_i > max_vxlanid)
|
156
|
+
max_vxlanid = vxlanid.to_i
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
options = {
|
149
163
|
"Name" => network_name,
|
150
164
|
"CheckDuplicate" => true,
|
151
|
-
# "Driver" => "bridge",
|
152
165
|
"Driver" => "overlay",
|
153
166
|
"EnableIPv6" => false,
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
# }
|
162
|
-
# ],
|
163
|
-
# "Options" => {
|
164
|
-
# # "foo" => "bar"
|
165
|
-
# }
|
166
|
-
# },
|
167
|
+
"IPAM" => {
|
168
|
+
"Driver" => "default",
|
169
|
+
"Config" => [
|
170
|
+
],
|
171
|
+
"Options" => {
|
172
|
+
}
|
173
|
+
},
|
167
174
|
"Internal" => false,
|
168
175
|
"Options" => {
|
169
|
-
"com.docker.network.driver.overlay.vxlanid_list" =>
|
176
|
+
"com.docker.network.driver.overlay.vxlanid_list" => (max_vxlanid + 1).to_s
|
170
177
|
},
|
171
178
|
"Labels" => {
|
172
179
|
# "com.example.some-label": "some-value",
|
173
180
|
# "com.example.some-other-label": "some-other-value"
|
174
181
|
}
|
175
182
|
}
|
176
|
-
|
177
|
-
response = connection.post('/networks/create', {}, body: opts.to_json, expects: [200, 201, 500], full_response: true)
|
178
|
-
if (response.status <= 201)
|
179
|
-
hash = JSON.parse(response.body)
|
180
|
-
response = connection.get("/networks/#{hash['Id']}", {}, expects: [200, 201], full_response: true)
|
181
|
-
hash = Docker::Util.parse_json(response.body)
|
182
|
-
network = Docker::Swarm::Network.new(self, hash)
|
183
|
-
return network
|
184
|
-
else
|
185
|
-
raise "Error creating network: HTTP-#{response.status} - #{response.body}"
|
186
|
-
end
|
183
|
+
create_network(options)
|
187
184
|
end
|
188
185
|
|
189
186
|
def find_network_by_name(network_name)
|
@@ -194,7 +191,7 @@ class Docker::Swarm::Swarm
|
|
194
191
|
end
|
195
192
|
return nil
|
196
193
|
end
|
197
|
-
|
194
|
+
|
198
195
|
# Return all of the Nodes.
|
199
196
|
def nodes
|
200
197
|
opts = {}
|
@@ -215,7 +212,7 @@ class Docker::Swarm::Swarm
|
|
215
212
|
|
216
213
|
def create_service(opts = {})
|
217
214
|
query = {}
|
218
|
-
response = self.connection.post('/services/create', query, :body => opts.to_json, expects: [201, 500], full_response: true)
|
215
|
+
response = self.connection.post('/services/create', query, :body => opts.to_json, expects: [201, 404, 409, 500], full_response: true)
|
219
216
|
if (response.status <= 201)
|
220
217
|
info = JSON.parse(response.body)
|
221
218
|
service_id = info['ID']
|
@@ -234,7 +231,7 @@ class Docker::Swarm::Swarm
|
|
234
231
|
return Docker::Swarm::Service.new(self, hash)
|
235
232
|
end
|
236
233
|
|
237
|
-
def
|
234
|
+
def find_service_by_name(name)
|
238
235
|
services.each do |service|
|
239
236
|
return service if (service.name == name)
|
240
237
|
end
|
@@ -253,23 +250,28 @@ class Docker::Swarm::Swarm
|
|
253
250
|
return items
|
254
251
|
end
|
255
252
|
|
256
|
-
def discover_nodes
|
257
|
-
# {discover_nodes: true, worker_docker_port: 2375}
|
258
|
-
|
259
|
-
end
|
260
|
-
|
261
253
|
# Initialize Swarm
|
262
254
|
def self.init(opts, connection)
|
263
255
|
query = {}
|
264
|
-
resp = connection.post('/swarm/init', query, :body => opts.to_json, full_response: true)
|
265
|
-
|
256
|
+
resp = connection.post('/swarm/init', query, :body => opts.to_json, full_response: true, expects: [200, 404, 500])
|
257
|
+
if (resp.status == 200)
|
258
|
+
swarm = Docker::Swarm::Swarm.swarm(opts, connection)
|
259
|
+
manager_node = swarm.nodes.find {|n|
|
260
|
+
(n.hash['ManagerStatus']) && (n.hash['ManagerStatus']['Leader'] == true)
|
261
|
+
}
|
262
|
+
listen_address = manager_node.hash['ManagerStatus']['Addr']
|
263
|
+
swarm.store_manager(connection, listen_address)
|
264
|
+
return swarm
|
265
|
+
else
|
266
|
+
raise "Bad response: #{resp.status} #{resp.body}"
|
267
|
+
end
|
266
268
|
end
|
267
269
|
|
268
270
|
# docker swarm join-token -q worker
|
269
271
|
def self.swarm(opts, connection)
|
270
272
|
query = {}
|
271
|
-
resp = connection.get('/swarm', query, :body => opts.to_json, expects: [200, 406], full_response: true)
|
272
|
-
if (resp.status == 406)
|
273
|
+
resp = connection.get('/swarm', query, :body => opts.to_json, expects: [200, 404, 406], full_response: true)
|
274
|
+
if (resp.status == 406) || (resp.status == 404)
|
273
275
|
return nil
|
274
276
|
elsif (resp.status == 200)
|
275
277
|
hash = JSON.parse(resp.body)
|
@@ -290,11 +292,16 @@ class Docker::Swarm::Swarm
|
|
290
292
|
|
291
293
|
def self.find(connection, options = {})
|
292
294
|
query = {}
|
293
|
-
response = connection.get('/swarm', query, expects: [200, 406], full_response: true)
|
295
|
+
response = connection.get('/swarm', query, expects: [200, 404, 406], full_response: true)
|
294
296
|
if (response.status == 200)
|
295
297
|
swarm = Docker::Swarm::Swarm.new(JSON.parse(response.body), connection, options)
|
298
|
+
manager_node = swarm.nodes.find {|n|
|
299
|
+
(n.hash['ManagerStatus']) && (n.hash['ManagerStatus']['Leader'] == true)
|
300
|
+
}
|
301
|
+
listen_address = manager_node.hash['ManagerStatus']['Addr']
|
302
|
+
swarm.store_manager(connection, listen_address)
|
296
303
|
return swarm
|
297
|
-
elsif (response.status
|
304
|
+
elsif (response.status > 200)
|
298
305
|
return nil
|
299
306
|
else
|
300
307
|
raise "Error finding swarm: HTTP-#{response.status} #{response.body}"
|
data/lib/docker/swarm/task.rb
CHANGED
@@ -19,6 +19,12 @@ class Docker::Swarm::Task
|
|
19
19
|
def service_id
|
20
20
|
@hash['ServiceID']
|
21
21
|
end
|
22
|
+
|
23
|
+
def service
|
24
|
+
return @swarm.services.find { |service|
|
25
|
+
self.service_id == service.id
|
26
|
+
}
|
27
|
+
end
|
22
28
|
|
23
29
|
def node_id
|
24
30
|
@hash['NodeID']
|
@@ -36,5 +42,15 @@ class Docker::Swarm::Task
|
|
36
42
|
@hash['Status']['State'].to_sym
|
37
43
|
end
|
38
44
|
|
45
|
+
def networks
|
46
|
+
all_networks = @swarm.networks
|
47
|
+
nets = []
|
48
|
+
self.hash['NetworksAttachments'].each do |net_hash|
|
49
|
+
hash = net_hash['Network']
|
50
|
+
network_id = hash['ID']
|
51
|
+
nets << all_networks.find {|net| net.id == network_id}
|
52
|
+
end
|
53
|
+
return nets
|
54
|
+
end
|
39
55
|
|
40
56
|
end
|
data/lib/docker/swarm/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: docker-swarm-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Moore / Rogue Wave Software
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|