sensu-plugins-docker-swarm 3.3.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 +7 -0
- data/CHANGELOG.md +179 -0
- data/LICENSE +22 -0
- data/README.md +40 -0
- data/bin/check-container-logs.rb +199 -0
- data/bin/check-container.rb +93 -0
- data/bin/check-docker-container.rb +108 -0
- data/bin/check-service-logs.rb +199 -0
- data/bin/check-service.rb +102 -0
- data/bin/metrics-docker-container.rb +127 -0
- data/bin/metrics-docker-info.rb +65 -0
- data/bin/metrics-docker-stats.rb +219 -0
- data/lib/sensu-plugins-docker.rb +1 -0
- data/lib/sensu-plugins-docker/client_helpers.rb +60 -0
- data/lib/sensu-plugins-docker/version.rb +9 -0
- metadata +271 -0
@@ -0,0 +1,93 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# check-container
|
4
|
+
#
|
5
|
+
# DESCRIPTION:
|
6
|
+
# This is a simple check script for Sensu to check that a Docker container is
|
7
|
+
# running. You can pass in either a container id or a container name.
|
8
|
+
#
|
9
|
+
# OUTPUT:
|
10
|
+
# plain text
|
11
|
+
#
|
12
|
+
# PLATFORMS:
|
13
|
+
# Linux
|
14
|
+
#
|
15
|
+
# DEPENDENCIES:
|
16
|
+
# gem: sensu-plugin
|
17
|
+
#
|
18
|
+
# USAGE:
|
19
|
+
# check-container.rb -H /var/run/docker.sock -N c92d402a5d14
|
20
|
+
# CheckDockerContainer OK: c92d402a5d14 is running on /var/run/docker.sock.
|
21
|
+
#
|
22
|
+
# check-container.rb -H https://127.0.0.1:2376 -N circle_burglar
|
23
|
+
# CheckDockerContainer CRITICAL: circle_burglar is not running on https://127.0.0.1:2376
|
24
|
+
#
|
25
|
+
# NOTES:
|
26
|
+
# => State.running == true -> OK
|
27
|
+
# => State.running == false -> CRITICAL
|
28
|
+
# => Not Found -> CRITICAL
|
29
|
+
# => Can't connect to Docker -> WARNING
|
30
|
+
# => Other exception -> WARNING
|
31
|
+
#
|
32
|
+
# LICENSE:
|
33
|
+
# Copyright 2014 Sonian, Inc. and contributors. <support@sensuapp.org>
|
34
|
+
# Released under the same terms as Sensu (the MIT license); see LICENSE
|
35
|
+
# for details.
|
36
|
+
#
|
37
|
+
|
38
|
+
require 'sensu-plugin/check/cli'
|
39
|
+
require 'sensu-plugins-docker/client_helpers'
|
40
|
+
|
41
|
+
#
|
42
|
+
# Check Docker Container
|
43
|
+
#
|
44
|
+
class CheckDockerContainer < Sensu::Plugin::Check::CLI
|
45
|
+
option :docker_host,
|
46
|
+
short: '-H DOCKER_HOST',
|
47
|
+
long: '--docker-host DOCKER_HOST',
|
48
|
+
description: 'Docker API URI. https://host, https://host:port, http://host, http://host:port, host:port, unix:///path'
|
49
|
+
|
50
|
+
option :container,
|
51
|
+
short: '-N CONTAINER',
|
52
|
+
long: '--container-name CONTAINER',
|
53
|
+
required: true
|
54
|
+
|
55
|
+
option :tag,
|
56
|
+
short: '-t TAG',
|
57
|
+
long: '--tag TAG'
|
58
|
+
|
59
|
+
option :allowexited,
|
60
|
+
short: '-x',
|
61
|
+
long: '--allow-exited',
|
62
|
+
boolean: true,
|
63
|
+
description: 'Do not raise alert if container has exited without error'
|
64
|
+
|
65
|
+
def run
|
66
|
+
@client = DockerApi.new(config[:docker_host])
|
67
|
+
path = "/containers/#{config[:container]}/json"
|
68
|
+
response = @client.call(path, false)
|
69
|
+
if response.code.to_i == 404
|
70
|
+
critical "Container #{config[:container]} is not running on #{@client.uri}"
|
71
|
+
end
|
72
|
+
body = parse_json(response)
|
73
|
+
container_running = body['State']['Running']
|
74
|
+
if container_running
|
75
|
+
if config[:tag]
|
76
|
+
image = body['Config']['Image']
|
77
|
+
match = image.match(/^(?:([^\/]+)\/)?(?:([^\/]+)\/)?([^@:\/]+)(?:[@:](.+))?$/)
|
78
|
+
unless match && match[4] == config[:tag]
|
79
|
+
critical "#{config[:container]}'s tag is '#{match[4]}', especting '#{config[:tag]}'"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
ok "#{config[:container]} is running on #{@client.uri}."
|
83
|
+
elsif config[:allowexited] && body['State']['Status'] == 'exited'
|
84
|
+
if (body['State']['ExitCode']).zero?
|
85
|
+
ok "#{config[:container]} has exited without error on #{@client.uri}."
|
86
|
+
else
|
87
|
+
critical "#{config[:container]} has exited with status code #{body['State']['ExitCode']} on #{@client.uri}."
|
88
|
+
end
|
89
|
+
else
|
90
|
+
critical "#{config[:container]} is #{body['State']['Status']} on #{@client.uri}."
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# check-docker-container
|
4
|
+
#
|
5
|
+
# DESCRIPTION:
|
6
|
+
# This is a simple check script for Sensu to check the number of a Docker Container
|
7
|
+
#
|
8
|
+
# OUTPUT:
|
9
|
+
# plain text
|
10
|
+
#
|
11
|
+
# PLATFORMS:
|
12
|
+
# Linux
|
13
|
+
#
|
14
|
+
# DEPENDENCIES:
|
15
|
+
# gem: sensu-plugin
|
16
|
+
# gem: net_http_unix
|
17
|
+
#
|
18
|
+
# USAGE:
|
19
|
+
# check-docker-container.rb -w 3 -c 3
|
20
|
+
# => 1 container running = OK.
|
21
|
+
# => 4 container running = CRITICAL
|
22
|
+
#
|
23
|
+
# check-docker-container.rb -H /var/run/docker.sock -w 3 -c 3
|
24
|
+
# => 1 container running = OK.
|
25
|
+
# => 4 container running = CRITICAL
|
26
|
+
#
|
27
|
+
# check-docker-container.rb -H https://127.0.0.1:2376 -w 3 -c 3
|
28
|
+
# => 1 container running = OK.
|
29
|
+
# => 4 container running = CRITICAL
|
30
|
+
#
|
31
|
+
# NOTES:
|
32
|
+
#
|
33
|
+
# LICENSE:
|
34
|
+
# Author Yohei Kawahara <inokara@gmail.com>
|
35
|
+
# Released under the same terms as Sensu (the MIT license); see LICENSE
|
36
|
+
# for details.
|
37
|
+
#
|
38
|
+
|
39
|
+
require 'sensu-plugin/check/cli'
|
40
|
+
require 'sensu-plugins-docker/client_helpers'
|
41
|
+
|
42
|
+
#
|
43
|
+
# Check Docker Containers
|
44
|
+
#
|
45
|
+
class CheckDockerContainers < Sensu::Plugin::Check::CLI
|
46
|
+
option :docker_host,
|
47
|
+
description: 'Docker API URI. https://host, https://host:port, http://host, http://host:port, host:port, unix:///path',
|
48
|
+
short: '-H DOCKER_HOST',
|
49
|
+
long: '--docker-host DOCKER_HOST'
|
50
|
+
|
51
|
+
option :warn_over,
|
52
|
+
short: '-W N',
|
53
|
+
long: '--warn-over N',
|
54
|
+
description: 'Trigger a warning if over a number',
|
55
|
+
proc: proc(&:to_i)
|
56
|
+
|
57
|
+
option :crit_over,
|
58
|
+
short: '-C N',
|
59
|
+
long: '--critical-over N',
|
60
|
+
description: 'Trigger a critical if over a number',
|
61
|
+
proc: proc(&:to_i)
|
62
|
+
|
63
|
+
option :warn_under,
|
64
|
+
short: '-w N',
|
65
|
+
long: '--warn-under N',
|
66
|
+
description: 'Trigger a warning if under a number',
|
67
|
+
proc: proc(&:to_i),
|
68
|
+
default: 1
|
69
|
+
|
70
|
+
option :crit_under,
|
71
|
+
short: '-c N',
|
72
|
+
long: '--critical-under N',
|
73
|
+
description: 'Trigger a critical if under a number',
|
74
|
+
proc: proc(&:to_i),
|
75
|
+
default: 1
|
76
|
+
|
77
|
+
def under_message(crit_under, count)
|
78
|
+
"Less than #{crit_under} containers running. #{count} running."
|
79
|
+
end
|
80
|
+
|
81
|
+
def over_message(crit_over, count)
|
82
|
+
"More than #{crit_over} containers running. #{count} running."
|
83
|
+
end
|
84
|
+
|
85
|
+
def evaluate_count(count)
|
86
|
+
# #YELLOW
|
87
|
+
if config.key?(:crit_under) && count < config[:crit_under]
|
88
|
+
critical under_message(config[:crit_under], count)
|
89
|
+
# #YELLOW
|
90
|
+
elsif config.key?(:crit_over) && count > config[:crit_over]
|
91
|
+
critical over_message(config[:crit_over], count)
|
92
|
+
# #YELLOW
|
93
|
+
elsif config.key?(:warn_under) && count < config[:warn_under]
|
94
|
+
warning under_message(config[:warn_under], count)
|
95
|
+
# #YELLOW
|
96
|
+
elsif config.key?(:warn_over) && count > config[:warn_over]
|
97
|
+
warning over_message(config[:warn_over], count)
|
98
|
+
else
|
99
|
+
ok
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def run
|
104
|
+
@client = DockerApi.new(config[:docker_host])
|
105
|
+
containers = @client.parse('/containers/json')
|
106
|
+
evaluate_count containers.size
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# check-service-logs
|
4
|
+
#
|
5
|
+
# DESCRIPTION:
|
6
|
+
# Checks docker logs for specified strings
|
7
|
+
# with the option to ignore lines if they contain specified substrings.
|
8
|
+
#
|
9
|
+
# OUTPUT:
|
10
|
+
# plain text
|
11
|
+
#
|
12
|
+
# PLATFORMS:
|
13
|
+
# Linux
|
14
|
+
#
|
15
|
+
# DEPENDENCIES:
|
16
|
+
# gem: sensu-plugin
|
17
|
+
# gem: net_http_unix
|
18
|
+
#
|
19
|
+
# USAGE:
|
20
|
+
# # Check only one service
|
21
|
+
# check-service-logs.rb -H /tmp/docker.sock -N logspout -r 'problem sending' -r 'i/o timeout' -i 'Remark:' -i 'The configuration is'
|
22
|
+
# => 1 service running = OK
|
23
|
+
# => 4 service running = CRITICAL
|
24
|
+
#
|
25
|
+
# # Check multiple services
|
26
|
+
# check-service-logs.rb -H /tmp/docker.sock -N logspout -N logtest -r 'problem sending' -r 'i/o timeout' -i 'Remark:' -i 'The configuration is'
|
27
|
+
# => 1 service running = OK
|
28
|
+
# => 4 service running = CRITICAL
|
29
|
+
#
|
30
|
+
# # Check all services
|
31
|
+
# check-service-logs.rb -H /tmp/docker.sock -r 'problem sending' -r 'i/o timeout' -i 'Remark:' -i 'The configuration is'
|
32
|
+
# => 1 services running = OK
|
33
|
+
# => 4 services running = CRITICAL
|
34
|
+
#
|
35
|
+
# NOTES:
|
36
|
+
# The API parameter required to use the limited lookback (-t) was introduced
|
37
|
+
# the Docker server API version 1.19. This check may still work on older API
|
38
|
+
# versions if you don't want to limit the timestamps of logs.
|
39
|
+
#
|
40
|
+
# LICENSE:
|
41
|
+
# Author: Nathan Newman <newmannh@gmail.com>, Kel Cecil <kelcecil@praisechaos.com>
|
42
|
+
# Released under the same terms as Sensu (the MIT license); see LICENSE
|
43
|
+
# for details.
|
44
|
+
#
|
45
|
+
|
46
|
+
require 'sensu-plugin/check/cli'
|
47
|
+
require 'sensu-plugins-docker/client_helpers'
|
48
|
+
|
49
|
+
class ServiceLogChecker < Sensu::Plugin::Check::CLI
|
50
|
+
option :docker_host,
|
51
|
+
description: 'Docker API URI. https://host, https://host:port, http://host, http://host:port, host:port, unix:///path',
|
52
|
+
short: '-H DOCKER_HOST',
|
53
|
+
long: '--docker-host DOCKER_HOST'
|
54
|
+
|
55
|
+
option :service,
|
56
|
+
description: 'name of service; can be used multiple times. /!\ All running services will be check if this options is not provided',
|
57
|
+
short: '-N service',
|
58
|
+
long: '--service-name service',
|
59
|
+
default: [],
|
60
|
+
proc: proc { |flag| (@options[:service][:accumulated] ||= []).push(flag) }
|
61
|
+
|
62
|
+
option :red_flags,
|
63
|
+
description: 'String whose presence (case-insensitive by default) in a log line indicates an error; can be used multiple times',
|
64
|
+
short: '-r ERR_STRING',
|
65
|
+
long: '--red-flag ERR_STRING',
|
66
|
+
default: [],
|
67
|
+
proc: proc { |flag| (@options[:red_flags][:accumulated] ||= []).push(flag) }
|
68
|
+
|
69
|
+
option :ignore_list,
|
70
|
+
description: 'String whose presence (case-insensitive by default) in a log line indicates the line should be ignored; can be used multiple times',
|
71
|
+
short: '-i IGNSTR',
|
72
|
+
long: '--ignore-lines-with IGNSTR',
|
73
|
+
default: [],
|
74
|
+
proc: proc { |flag| (@options[:ignore_list][:accumulated] ||= []).push(flag) }
|
75
|
+
|
76
|
+
option :case_sensitive,
|
77
|
+
description: 'indicates all red_flag and ignore_list substring matching should be case-sensitive instead of the default case-insensitive',
|
78
|
+
short: '-c',
|
79
|
+
long: '--case-sensitive',
|
80
|
+
boolean: true
|
81
|
+
|
82
|
+
option :hours_ago,
|
83
|
+
description: 'Amount of time in hours to look back for log strings',
|
84
|
+
short: '-t HOURS',
|
85
|
+
long: '--hours-ago HOURS',
|
86
|
+
required: false
|
87
|
+
|
88
|
+
option :seconds_ago,
|
89
|
+
description: 'Amount of time in seconds to look back for log strings',
|
90
|
+
short: '-s SECONDS',
|
91
|
+
long: '--seconds-ago SECONDS',
|
92
|
+
required: false
|
93
|
+
|
94
|
+
option :check_all,
|
95
|
+
description: 'If all services are checked (no service name provided with -n) , check offline services too',
|
96
|
+
short: '-a',
|
97
|
+
long: '--all',
|
98
|
+
default: false,
|
99
|
+
boolean: true
|
100
|
+
|
101
|
+
option :disable_stdout,
|
102
|
+
description: 'Disable the check on STDOUT logs. By default both STDERR and STDOUT are checked',
|
103
|
+
short: '-1',
|
104
|
+
long: '--no-stdout',
|
105
|
+
default: true,
|
106
|
+
boolean: true,
|
107
|
+
proc: proc { false } # used to negate the false(default)->true boolean option behaviour to true(default)->false
|
108
|
+
|
109
|
+
option :disable_stderr,
|
110
|
+
description: 'Disable the check on STDERR logs. By default both STDERR and STDOUT are checked',
|
111
|
+
short: '-2',
|
112
|
+
long: '--no-stderr',
|
113
|
+
default: true,
|
114
|
+
boolean: true,
|
115
|
+
proc: proc { false } # used to negate the false(default)->true boolean option behaviour to true(default)->false
|
116
|
+
|
117
|
+
def calculate_timestamp(seconds_ago = nil)
|
118
|
+
seconds_ago = yield if block_given?
|
119
|
+
(Time.now - seconds_ago).to_i
|
120
|
+
end
|
121
|
+
|
122
|
+
def process_docker_logs(service_name)
|
123
|
+
path = "/services/#{service_name}/logs?stdout=#{config[:disable_stdout]}&stderr=#{config[:disable_stderr]}×tamps=true"
|
124
|
+
if config.key? :hours_ago
|
125
|
+
timestamp = calculate_timestamp { config[:hours_ago].to_i * 3600 }
|
126
|
+
elsif config.key? :seconds_ago
|
127
|
+
timestamp = calculate_timestamp config[:seconds_ago].to_i
|
128
|
+
end
|
129
|
+
path = "#{path}&since=#{timestamp}"
|
130
|
+
response = @client.call(path, false)
|
131
|
+
if response.code.to_i == 404
|
132
|
+
critical "service '#{service_name}' not found on #{@client.uri}"
|
133
|
+
end
|
134
|
+
yield remove_headers response.read_body
|
135
|
+
end
|
136
|
+
|
137
|
+
def remove_headers(raw_logs)
|
138
|
+
lines = raw_logs.split("\n")
|
139
|
+
lines.map! do |line|
|
140
|
+
# Check only logs generated with the 8 bits control
|
141
|
+
if !line.nil? && line.bytesize > 8 && /^(0|1|2)000$/ =~ line.byteslice(0, 4).unpack('C*').join('')
|
142
|
+
# Remove the first 8 bits and ansii colors too
|
143
|
+
line.byteslice(8, line.bytesize).gsub(/\x1b\[[\d;]*?m/, '')
|
144
|
+
end
|
145
|
+
end
|
146
|
+
# We want the most recent logs lines first
|
147
|
+
lines.compact.reverse.join("\n")
|
148
|
+
end
|
149
|
+
|
150
|
+
def includes_any?(str, array_of_substrings)
|
151
|
+
array_of_substrings.each do |substring|
|
152
|
+
return true if str.include? substring
|
153
|
+
end
|
154
|
+
false
|
155
|
+
end
|
156
|
+
|
157
|
+
def detect_problem(logs)
|
158
|
+
whiteflags = config[:ignore_list]
|
159
|
+
redflags = config[:red_flags]
|
160
|
+
unless config[:case_sensitive]
|
161
|
+
logs = logs.downcase
|
162
|
+
whiteflags.map!(&:downcase)
|
163
|
+
redflags.map!(&:downcase)
|
164
|
+
end
|
165
|
+
|
166
|
+
logs.split("\n").each do |line|
|
167
|
+
return line if !includes_any?(line, whiteflags) && includes_any?(line, redflags)
|
168
|
+
end
|
169
|
+
nil
|
170
|
+
end
|
171
|
+
|
172
|
+
def run
|
173
|
+
@client = DockerApi.new(config[:docker_host])
|
174
|
+
problem = []
|
175
|
+
problem_string = nil
|
176
|
+
path = "/services/json?all=#{config[:check_all]}"
|
177
|
+
services = config[:service]
|
178
|
+
if config[:service].none?
|
179
|
+
warn_msg = %(
|
180
|
+
Collecting logs from all services is dangerous and could lead to sensu client hanging depending on volume of logs.
|
181
|
+
This not recommended for production environments.
|
182
|
+
).gsub(/\s+/, ' ').strip
|
183
|
+
message warn_msg
|
184
|
+
end
|
185
|
+
services = @client.parse(path).map { |p| p['Names'][0].delete('/') } if services.none?
|
186
|
+
critical 'Check all services was asked but no services was found' if services.none?
|
187
|
+
services.each do |service|
|
188
|
+
process_docker_logs service do |log_chunk|
|
189
|
+
problem_string = detect_problem(log_chunk)
|
190
|
+
break unless problem_string.nil?
|
191
|
+
end
|
192
|
+
problem << "\tError found inside service : '#{service}'\n\t\t#{problem_string}" unless problem_string.nil?
|
193
|
+
end
|
194
|
+
problem_string = problem.join("\n")
|
195
|
+
critical "service(s) logs indicate problems :\n#{problem_string}" unless problem.none?
|
196
|
+
services_string = services.join(', ')
|
197
|
+
ok "No errors detected from logs inside service(s) : \n#{services_string}"
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# check-service
|
4
|
+
#
|
5
|
+
# DESCRIPTION:
|
6
|
+
# This is a simple check script for Sensu to check that a Docker service is
|
7
|
+
# running all of it's intended tasks. You can pass in either a service id or a service name.
|
8
|
+
#
|
9
|
+
# OUTPUT:
|
10
|
+
# plain text
|
11
|
+
#
|
12
|
+
# PLATFORMS:
|
13
|
+
# Linux
|
14
|
+
#
|
15
|
+
# DEPENDENCIES:
|
16
|
+
# gem: sensu-plugin
|
17
|
+
#
|
18
|
+
# USAGE:
|
19
|
+
# check-service.rb -H /var/run/docker.sock -N c92d402a5d14
|
20
|
+
# CheckDockerService OK: c92d402a5d14 is running on /var/run/docker.sock.
|
21
|
+
#
|
22
|
+
# check-service.rb -H https://127.0.0.1:2376 -N circle_burglar
|
23
|
+
# CheckDockerService CRITICAL: circle_burglar is not running on https://127.0.0.1:2376
|
24
|
+
#
|
25
|
+
# NOTES:
|
26
|
+
# => .Replicas == number of service's tasks -> OK
|
27
|
+
# => .Replicas != number of service's tasks -> CRITICAL
|
28
|
+
# => Not Found -> CRITICAL
|
29
|
+
# => Can't connect to Docker -> WARNING
|
30
|
+
# => Other exception -> WARNING
|
31
|
+
#
|
32
|
+
# LICENSE:
|
33
|
+
# Copyright 2014 Sonian, Inc. and contributors. <support@sensuapp.org>
|
34
|
+
# Released under the same terms as Sensu (the MIT license); see LICENSE
|
35
|
+
# for details.
|
36
|
+
#
|
37
|
+
|
38
|
+
require 'sensu-plugin/check/cli'
|
39
|
+
require 'sensu-plugins-docker/client_helpers'
|
40
|
+
|
41
|
+
#
|
42
|
+
# Check Docker Service
|
43
|
+
#
|
44
|
+
class CheckDockerService < Sensu::Plugin::Check::CLI
|
45
|
+
option :docker_host,
|
46
|
+
short: '-H DOCKER_HOST',
|
47
|
+
long: '--docker-host DOCKER_HOST',
|
48
|
+
description: 'Docker API URI. https://host, https://host:port, http://host, http://host:port, host:port, unix:///path'
|
49
|
+
|
50
|
+
option :service,
|
51
|
+
short: '-N SERVICE',
|
52
|
+
long: '--service-name service',
|
53
|
+
required: true
|
54
|
+
|
55
|
+
option :tag,
|
56
|
+
short: '-t TAG',
|
57
|
+
long: '--tag TAG'
|
58
|
+
|
59
|
+
option :allowexited,
|
60
|
+
short: '-x',
|
61
|
+
long: '--allow-exited',
|
62
|
+
boolean: true,
|
63
|
+
description: 'Do not raise alert if service has exited without error'
|
64
|
+
|
65
|
+
def run
|
66
|
+
# Connect a client to the remote/local docker socket
|
67
|
+
@client = DockerApi.new(config[:docker_host])
|
68
|
+
|
69
|
+
# Call /services and get the service we want to check
|
70
|
+
path = "/services?filters=%7B%22name%22%3A%7B%22#{config[:service]}%22%3Atrue%7D%7D"
|
71
|
+
response = @client.call(path, false)
|
72
|
+
if response.code.to_i == 404
|
73
|
+
critical "service #{config[:service]} is not running on #{@client.uri} bb"
|
74
|
+
end
|
75
|
+
|
76
|
+
# Pass the number of replicas the service should be running
|
77
|
+
body = parse_json(response)
|
78
|
+
intended_replicas = body[0]['Spec']['Mode']['Replicated']['Replicas']
|
79
|
+
|
80
|
+
# Call /tasks to get the number of running replicas (this is how `docker service ls` works)
|
81
|
+
running_replicas = 0
|
82
|
+
path = "/tasks?filters=%7B%22name%22%3A%7B%22#{config[:service]}%22%3Atrue%7D%7D"
|
83
|
+
response = @client.call(path, false)
|
84
|
+
if response.code.to_i == 404
|
85
|
+
critical "service #{config[:service]} is not running on #{@client.uri}, tasks not found"
|
86
|
+
end
|
87
|
+
|
88
|
+
# Traverse the tasks and check if the state is running
|
89
|
+
tasks = parse_json(response)
|
90
|
+
tasks.each do |task|
|
91
|
+
if task['Status']['State'] == 'running'
|
92
|
+
running_replicas += 1
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# If the number of running replicas is not what the service expects, return critical
|
97
|
+
if intended_replicas != running_replicas
|
98
|
+
critical "service #{config[:service]} is not running the intended number of replicas"
|
99
|
+
end
|
100
|
+
ok "#{config[:service]} is running correctly on #{@client.uri}."
|
101
|
+
end
|
102
|
+
end
|