class COMAP::App
Rack App
Public Class Methods
new( docker_host: 'http://127.0.0.1', docker_port: '2375', docker_ssl: '', metrics_path: '', network: '', services: [] )
click to toggle source
rubocop:disable Metrics/ParameterLists
# File lib/comap/app.rb, line 26 def initialize( docker_host: 'http://127.0.0.1', docker_port: '2375', docker_ssl: '', metrics_path: '', network: '', services: [] ) raise ArgumentError, 'No services given' if services.empty? raise ArgumentError, 'No network given' if network.nil? ssl_hash = parse_ssl(docker_ssl) @client = DockerClient.new(docker_host, docker_port, ssl_hash) @network = network @services = services @metrics_path = metrics_path error_msg = 'Could not retrieve Docker API version from '\ "#{docker_host}:#{docker_port} ssl:#{docker_ssl}" raise StandardError, error_msg if @client.call('version').nil? end
Public Instance Methods
call(_env)
click to toggle source
rubocop:enable Metrics/ParameterLists
# File lib/comap/app.rb, line 48 def call(_env) ['200', { 'Content-Type' => 'text/plain' }, [body]] end
Private Instance Methods
add_label(line, service, slot)
click to toggle source
# File lib/comap/app.rb, line 90 def add_label(line, service, slot) replace = %(service="#{service}",container="#{service}.#{slot}") if line[/{.*?\}/].nil? line.sub(/ /, "{#{replace}} ") else line.sub(/(\{(.*)\})/, "{\\2,#{replace}}") end end
body()
click to toggle source
# File lib/comap/app.rb, line 54 def body @services.map do |s| service, port = s.split(':') service_metrics(service, port) end.compact.map(&flat_hash).join end
container_metrics(url, service, slot)
click to toggle source
# File lib/comap/app.rb, line 70 def container_metrics(url, service, slot) data = scrape_metrics(url, service) return {} if data.nil? data.lines.each_with_object({}) do |value, hash| next hash[value] = nil if value.start_with?('#') (hash[hash.keys.last] ||= []) << add_label(value, service, slot) end.compact end
containers(service)
click to toggle source
# File lib/comap/app.rb, line 99 def containers(service) running_tasks(service).map do |task| { 'slot' => task['Slot'] || task['NodeID'], 'ip' => ip(task).split('/').first } end.uniq end
flat_hash()
click to toggle source
# File lib/comap/app.rb, line 144 def flat_hash proc do |item| item.map { |key, value| "#{key}#{value.join}" } end end
ip(task)
click to toggle source
# File lib/comap/app.rb, line 118 def ip(task) task['NetworksAttachments'].select do |h| h['Network']['Spec']['Name'] == @network end.first['Addresses'].first end
merge_proc()
click to toggle source
# File lib/comap/app.rb, line 138 def merge_proc proc do |old, new| old.merge(new) { |_, value1, value2| value1 + value2 } end end
parse_ssl(docker_ssl)
click to toggle source
helpers
# File lib/comap/app.rb, line 126 def parse_ssl(docker_ssl) docker_ssl.split(',').map do |opt| k, v = opt.split('=') if k.include?('cert') v = OpenSSL::X509::Certificate.new(File.read(v)) elsif k.include? 'key' v = OpenSSL::PKey::RSA.new(File.read(v)) end [k, v] end.to_h end
running_tasks(service)
click to toggle source
# File lib/comap/app.rb, line 108 def running_tasks(service) filters = { 'service' => { service => true }, 'desired-state' => { 'running' => true } } @client.call('tasks', filters).keep_if do |task| task['Status']['State'] == 'running' if task.is_a?(Hash) end end
scrape_metrics(url, service)
click to toggle source
# File lib/comap/app.rb, line 81 def scrape_metrics(url, service) Faraday.get(url) do |req| req.options.timeout = 2 req.options.open_timeout = 1 end.body rescue StandardError puts "Could not connect to #{service} endpoint #{url}" end
service_metrics(service, port)
click to toggle source
# File lib/comap/app.rb, line 61 def service_metrics(service, port) containers(service).sort_by { |c| c['slot'] }.map do |container| next puts "#{service} service not found" if container.empty? url = "http://#{container['ip']}:#{port}/#{@metrics_path}" container_metrics(url, service, container['slot']) end.reduce(&merge_proc) end