diff --git a/dps.rb b/dps.rb new file mode 100755 index 0000000..79315b6 --- /dev/null +++ b/dps.rb @@ -0,0 +1,130 @@ +#!/usr/bin/env ruby +require 'json' +require 'socket' +require 'net/http' + +COLOR_GREEN = "" +COLOR_RED = "" +COLOR_GRAY = "" +COLOR_RESET = "" + +class Container + FIELDS = [:state, :dup, :ouroboros, :name, :vhosts, :nginx_allow, :status, :image, :ports] + @@lengths = Hash.new(0) + + def initialize(data) + @strings = {} + @data = data + + set :state, (@data[:State]=="running" ? COLOR_GREEN : COLOR_RED) + @data[:State].capitalize + COLOR_RESET + set :dup, @data[:Labels][:"de.fabianonline.dup"]=="true" ? "✓" : "" + set :ouroboros, @data[:Labels][:"com.centurylinklabs.watchtower.enable"]=="true" ? "✓" : "" + set :name, @data[:Names].first[1..-1] + + vh = @data[:Labels][:"nginx_virtual_host"]&.split(",")&.collect(&:strip) + if vh.nil? || vh.count==0 + vh = "" + elsif vh.count==1 + vh = vh.first + else + if FULL + vh = vh.join(", ") + else + vh = vh.first + ",…" + end + end + + set :vhosts, vh + + p = @data[:Ports].sort_by{|p| p[:PrivatePort]}.collect do |p| + type = p[:Type]=="tcp" ? "" : "/#{p[:Type]}" + if p[:PrivatePort]==p[:PublicPort] + "#{COLOR_GREEN}#{p[:PrivatePort]}#{type}" + elsif p[:PublicPort]==nil + "#{COLOR_GRAY}#{p[:PrivatePort]}#{type}" + else + "#{COLOR_RED}#{p[:PrivatePort]}->#{p[:PublicPort]}#{type}" + end + end.join(" ") + + set :nginx_allow, @data[:Labels][:"nginx_allow"] + st = @data[:Status] + if st.end_with?("(healthy)") + st = COLOR_GREEN + st.gsub("(healthy)", "(v)") + COLOR_RESET + elsif st.end_with?("(unhealthy)") + st = COLOR_RED + st.gsub("(unhealthy)", "(x)") + COLOR_RESET + end + set :status, st + im = @data[:Image] + im = im.split(":")[0] unless FULL + set :image, im + set :ports, p + end + + def set(key, value) + @data[key] = value + @@lengths[key] = [@@lengths[key], value.cleaned.length].max if value + end + + def self.lengths; FIELDS.map{|k| @@lengths[k]}; end + + def data + FIELDS.map{|k| @data[k]} + end +end + +class String + def cleaned + self.gsub(/\[.+?m/, "") + end + + def fix_length(len) + l = self.cleaned.length + shortened = self.length - l + + if l >= len + return self.slice(0, len + shortened) + else + return self + (" " * (len - l)) + end + end +end + +def fetch_data + socket = UNIXSocket.new("/var/run/docker.sock") + request = "GET /v1.24/containers/json?all=1 HTTP/1.0\r\n\r\n"#Host: localhost\r\n\r\n" + socket.write(request) + + response = "" + + loop do + break if socket.eof? + line = socket.gets + break if line=="\r\n" + end + + until socket.eof? + line = socket.gets + response += line + end + + return JSON.parse(response, symbolize_names: true) +end + +FULL = ARGV[0]=="--full" + +data = fetch_data +data = data.map{|c| Container.new(c).data} + +lengths = Container.lengths + +data.sort_by{|d| d[3]}.each do |row| + row.each_with_index do |d, index| + if index==row.length-1 + print d.to_s + else + print d.to_s.fix_length(lengths[index]) + " " + end + end + puts +end