comap 1.0.0.pre.a
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/.gitignore +14 -0
- data/.gitlab-ci.yml +56 -0
- data/.kitchen.yml +125 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/Berksfile +8 -0
- data/CONTRIBUTING.md +62 -0
- data/Dockerfile +15 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +327 -0
- data/LICENSE +202 -0
- data/README.md +65 -0
- data/Rakefile +32 -0
- data/bin/console +30 -0
- data/bin/setup +23 -0
- data/comap.gemspec +53 -0
- data/exe/comap +28 -0
- data/lib/comap.rb +100 -0
- data/lib/comap/app.rb +142 -0
- data/lib/comap/docker_client.rb +42 -0
- data/lib/comap/version.rb +21 -0
- data/metadata.rb +17 -0
- data/recipes/build_comap.rb +35 -0
- data/recipes/launch_comap.rb +66 -0
- metadata +183 -0
data/lib/comap/app.rb
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2017-2018 Make.org
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'faraday'
|
19
|
+
require 'openssl'
|
20
|
+
|
21
|
+
# Main module
|
22
|
+
module COMAP
|
23
|
+
# Rack App
|
24
|
+
class App
|
25
|
+
# rubocop:disable Metrics/ParameterLists
|
26
|
+
def initialize(
|
27
|
+
docker_host: 'http://127.0.0.1',
|
28
|
+
docker_port: '2375',
|
29
|
+
docker_ssl: '',
|
30
|
+
metrics_path: '',
|
31
|
+
network: '',
|
32
|
+
services: []
|
33
|
+
)
|
34
|
+
raise ArgumentError, 'No services given' if services.empty?
|
35
|
+
raise ArgumentError, 'No network given' if network.nil?
|
36
|
+
ssl_hash = parse_ssl(docker_ssl)
|
37
|
+
@client = DockerClient.new(docker_host, docker_port, ssl_hash)
|
38
|
+
@network = network
|
39
|
+
@services = services
|
40
|
+
@metrics_path = metrics_path
|
41
|
+
error_msg = 'Could not retrieve Docker API version from '\
|
42
|
+
"#{docker_host}:#{docker_port} ssl:#{docker_ssl}"
|
43
|
+
raise StandardError, error_msg if @client.call('version').nil?
|
44
|
+
end
|
45
|
+
# rubocop:enable Metrics/ParameterLists
|
46
|
+
|
47
|
+
def call(_env)
|
48
|
+
['200', { 'Content-Type' => 'text/plain' }, [body]]
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def body
|
54
|
+
@services.map do |s|
|
55
|
+
service, port = s.split(':')
|
56
|
+
service_metrics(service, port)
|
57
|
+
end.compact.map(&flat_hash).join
|
58
|
+
end
|
59
|
+
|
60
|
+
def service_metrics(service, port)
|
61
|
+
containers(service).sort_by { |c| c['slot'] }.map do |container|
|
62
|
+
next puts "#{service} service not found" if container.empty?
|
63
|
+
url = "http://#{container['ip']}:#{port}/#{@metrics_path}"
|
64
|
+
container_metrics(url, service, container['slot'])
|
65
|
+
end.reduce(&merge_proc)
|
66
|
+
end
|
67
|
+
|
68
|
+
def container_metrics(url, service, slot)
|
69
|
+
data = scrape_metrics(url, service)
|
70
|
+
return {} if data.nil?
|
71
|
+
data.lines.each_with_object({}) do |value, hash|
|
72
|
+
next hash[value] = nil if value.start_with?('#')
|
73
|
+
(hash[hash.keys.last] ||= []) << add_label(value, "#{service}.#{slot}")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def scrape_metrics(url, service)
|
78
|
+
Faraday.get(url) do |req|
|
79
|
+
req.options.timeout = 2
|
80
|
+
req.options.open_timeout = 1
|
81
|
+
end.body
|
82
|
+
rescue StandardError
|
83
|
+
puts "Could not connect to #{service} endpoint #{url}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def add_label(line, label)
|
87
|
+
replace = %(container="#{label}")
|
88
|
+
line.gsub(/ /, "{#{replace}} ").gsub(/}{/, ',')
|
89
|
+
end
|
90
|
+
|
91
|
+
def containers(service)
|
92
|
+
running_tasks(service).map do |task|
|
93
|
+
{
|
94
|
+
'slot' => task['Slot'],
|
95
|
+
'ip' => ip(task).split('/').first
|
96
|
+
}
|
97
|
+
end.uniq
|
98
|
+
end
|
99
|
+
|
100
|
+
def running_tasks(service)
|
101
|
+
filters = {
|
102
|
+
'service' => { service => true },
|
103
|
+
'desired-state' => { 'running' => true }
|
104
|
+
}
|
105
|
+
@client.call('tasks', filters).keep_if do |task|
|
106
|
+
task['Status']['State'] == 'running'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def ip(task)
|
111
|
+
task['NetworksAttachments'].select do |h|
|
112
|
+
h['Network']['Spec']['Name'] == @network
|
113
|
+
end.first['Addresses'].first
|
114
|
+
end
|
115
|
+
|
116
|
+
# helpers
|
117
|
+
|
118
|
+
def parse_ssl(docker_ssl)
|
119
|
+
docker_ssl.split(',').map do |opt|
|
120
|
+
k, v = opt.split('=')
|
121
|
+
if k.include?('cert')
|
122
|
+
v = OpenSSL::X509::Certificate.new(File.read(v))
|
123
|
+
elsif k.include? 'key'
|
124
|
+
v = OpenSSL::PKey::RSA.new(File.read(v))
|
125
|
+
end
|
126
|
+
[k, v]
|
127
|
+
end.to_h
|
128
|
+
end
|
129
|
+
|
130
|
+
def merge_proc
|
131
|
+
proc do |old, new|
|
132
|
+
old.merge(new) { |_, value1, value2| value1 + value2 }
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def flat_hash
|
137
|
+
proc do |item|
|
138
|
+
item.map { |key, value| "#{key}#{value.join}" }
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2017-2018 Make.org
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'faraday'
|
19
|
+
require 'json'
|
20
|
+
|
21
|
+
# Module Docker
|
22
|
+
module COMAP
|
23
|
+
# Simple Engine API client
|
24
|
+
class DockerClient
|
25
|
+
def initialize(url, port, ssl = {})
|
26
|
+
@conn = Faraday.new(url: "#{url}:#{port}", ssl: ssl) do |faraday|
|
27
|
+
faraday.options.params_encoder = Faraday::FlatParamsEncoder
|
28
|
+
faraday.adapter Faraday.default_adapter
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def call(route, filters = {})
|
33
|
+
response = @conn.get(route) do |req|
|
34
|
+
req.params['filters'] = filters.to_json
|
35
|
+
end
|
36
|
+
JSON.parse(response.body)
|
37
|
+
rescue StandardError => e
|
38
|
+
puts "Could not connect to Docker API #{@conn.url_prefix}"
|
39
|
+
puts e.message
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2017-2018 Make.org
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
# Define version
|
19
|
+
module COMAP
|
20
|
+
VERSION = '1.0.0-a'
|
21
|
+
end
|
data/metadata.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
name 'comap-test'
|
4
|
+
maintainer 'Make.org'
|
5
|
+
maintainer_email 'sre@make.org'
|
6
|
+
license 'Apache-2.0'
|
7
|
+
description 'Integration tests for Comap'
|
8
|
+
long_description 'Integration tests for Comap'
|
9
|
+
source_url 'https://gitlab.com/sre-gems/comap'
|
10
|
+
issues_url 'https://gitlab.com/sre-gems/comap/issues'
|
11
|
+
version '1.0.0'
|
12
|
+
|
13
|
+
chef_version '>= 13.0'
|
14
|
+
|
15
|
+
supports 'centos', '>= 7.4'
|
16
|
+
|
17
|
+
depends 'docker-platform'
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Make.org
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
# Build comap docker image and launch it
|
19
|
+
directory '/root/pkg'
|
20
|
+
|
21
|
+
cookbook_file '/root/Dockerfile' do
|
22
|
+
source 'Dockerfile'
|
23
|
+
notifies :run, 'execute[docker build comap]', :delayed
|
24
|
+
end
|
25
|
+
|
26
|
+
cookbook_file '/root/pkg/comap.gem' do
|
27
|
+
source 'comap.gem'
|
28
|
+
notifies :run, 'execute[docker build comap]', :delayed
|
29
|
+
end
|
30
|
+
|
31
|
+
execute 'docker build comap' do
|
32
|
+
command 'docker build . -t makeorg/comap'
|
33
|
+
cwd '/root'
|
34
|
+
action :nothing
|
35
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Make.org
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
# Create secrets
|
19
|
+
dir = '/root/.docker'
|
20
|
+
%w[ca.pem cert.pem key.pem].each do |secret|
|
21
|
+
execute "docker secret create #{secret} #{dir}/#{secret}" do
|
22
|
+
not_if "docker secret ls | grep #{secret}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
metrics_content = <<~CONTENT
|
27
|
+
# TYPE metrics_sample_seconds gauge
|
28
|
+
metrics_sample_seconds 42
|
29
|
+
# TYPE metrics_sample_2_seconds gauge
|
30
|
+
metrics_sample_2_seconds 24
|
31
|
+
CONTENT
|
32
|
+
|
33
|
+
docker_platform_service 'metrics' do
|
34
|
+
options(
|
35
|
+
mode: 'replicated',
|
36
|
+
replicas: 2,
|
37
|
+
network: 'kitchen',
|
38
|
+
publish: '5678:5678'
|
39
|
+
)
|
40
|
+
image 'hashicorp/http-echo'
|
41
|
+
command "-text '#{metrics_content.chomp("\n")}'"
|
42
|
+
action :create
|
43
|
+
end
|
44
|
+
|
45
|
+
server = 'https://comap-swarm-manager-centos-7'
|
46
|
+
ssl = {
|
47
|
+
'verify' => false, # https://github.com/berkshelf/berkshelf/issues/1458
|
48
|
+
'client_cert' => '/run/secrets/cert.pem',
|
49
|
+
'client_key' => '/run/secrets/key.pem',
|
50
|
+
'ca_file' => '/run/secrets/ca.pem'
|
51
|
+
}
|
52
|
+
ssl_opt = ssl.map { |k, v| "#{k}=#{v}" }.join(',')
|
53
|
+
puts "-H #{server} -p 2376 -s #{ssl_opt} -n kitchen metrics:5678"
|
54
|
+
|
55
|
+
# TODO: give options as an array in docker-platform
|
56
|
+
docker_platform_service 'comap' do
|
57
|
+
options(
|
58
|
+
mode: 'replicated',
|
59
|
+
network: 'kitchen',
|
60
|
+
publish: '9100:9100',
|
61
|
+
secret: %w[cert.pem key.pem ca.pem]
|
62
|
+
)
|
63
|
+
image 'makeorg/comap'
|
64
|
+
command "-H #{server} -p 2376 -s #{ssl_opt} -n kitchen metrics:5678"
|
65
|
+
action :create
|
66
|
+
end
|
metadata
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: comap
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.pre.a
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sylvain Arrambourg
|
8
|
+
- Samuel Bernard
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
|
+
cert_chain: []
|
12
|
+
date: 2018-02-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.16'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.16'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '12.2'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '12.2'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rspec
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '3'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '3'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rubocop
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0.51'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0.51'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: webmock
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '2.0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '2.0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: faraday
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0.13'
|
91
|
+
type: :runtime
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0.13'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: json
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - "~>"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '2.0'
|
105
|
+
type: :runtime
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '2.0'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: thin
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - "~>"
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '1.7'
|
119
|
+
type: :runtime
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - "~>"
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '1.7'
|
126
|
+
description: Container Orchestrator Metrics Aggregator for Prometheus
|
127
|
+
email:
|
128
|
+
- sar@make.org
|
129
|
+
executables:
|
130
|
+
- comap
|
131
|
+
extensions: []
|
132
|
+
extra_rdoc_files: []
|
133
|
+
files:
|
134
|
+
- ".gitignore"
|
135
|
+
- ".gitlab-ci.yml"
|
136
|
+
- ".kitchen.yml"
|
137
|
+
- ".rspec"
|
138
|
+
- ".ruby-version"
|
139
|
+
- ".travis.yml"
|
140
|
+
- Berksfile
|
141
|
+
- CONTRIBUTING.md
|
142
|
+
- Dockerfile
|
143
|
+
- Gemfile
|
144
|
+
- Gemfile.lock
|
145
|
+
- LICENSE
|
146
|
+
- README.md
|
147
|
+
- Rakefile
|
148
|
+
- bin/console
|
149
|
+
- bin/setup
|
150
|
+
- comap.gemspec
|
151
|
+
- exe/comap
|
152
|
+
- lib/comap.rb
|
153
|
+
- lib/comap/app.rb
|
154
|
+
- lib/comap/docker_client.rb
|
155
|
+
- lib/comap/version.rb
|
156
|
+
- metadata.rb
|
157
|
+
- recipes/build_comap.rb
|
158
|
+
- recipes/launch_comap.rb
|
159
|
+
homepage: https://gitlab.com/sre-gems/comap
|
160
|
+
licenses:
|
161
|
+
- Apache-2.0
|
162
|
+
metadata: {}
|
163
|
+
post_install_message:
|
164
|
+
rdoc_options: []
|
165
|
+
require_paths:
|
166
|
+
- lib
|
167
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - ">="
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
172
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
|
+
requirements:
|
174
|
+
- - ">"
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: 1.3.1
|
177
|
+
requirements: []
|
178
|
+
rubyforge_project:
|
179
|
+
rubygems_version: 2.7.3
|
180
|
+
signing_key:
|
181
|
+
specification_version: 4
|
182
|
+
summary: Container Orchestrator Metrics Aggregator for Prometheus
|
183
|
+
test_files: []
|