lib/jarl/docker.rb in jarl-0.7.0 vs lib/jarl/docker.rb in jarl-0.8.1
- old
+ new
@@ -62,13 +62,21 @@
Container.new id
end
@docker_containers_running
end
+ # Returns `docker ps` info inspector instance
+ #
+ def self.ps
+ @docker_ps ||= Ps.new
+ end
+
+
# Reloads lists of images and containers
#
def self.reload!
+ @docker_ps = nil
@docker_images = nil
@docker_images_used = nil
@docker_containers_running = nil
end
@@ -132,10 +140,56 @@
" --name #{container_name} #{params[:image]} #{params[:command]}"
# puts docker_cmd
sh docker_cmd
end
+ # `docker ps` info inspector
+ #
+ class Ps
+ FIELDS = [
+ 'CONTAINER ID', 'IMAGE', 'COMMAND', 'CREATED', 'STATUS', 'PORTS', 'NAMES'
+ ]
+
+ attr_reader :entries
+
+ def initialize
+ lines = `docker ps`.split("\n")
+ @headers = lines.shift
+ @data = lines
+ @entries = lines.map do |line|
+ FIELDS.map { |name| [name, field(line, name)] }.to_h
+ end
+ end
+
+ def field_i_start(name)
+ i_start = @headers.index(name)
+ fail "Failed to find the field #{name} in docker ps" unless i_start
+ i_start
+ end
+
+ # @return [nil,Integer] right index for field or -1 if the field is rightmost
+ #
+ def field_i_end(name)
+ i_start = field_i_start(name)
+ r_headers = @headers[i_start..-1].sub(/^#{name}/, '')
+ m = r_headers.match(/^(\s+)/)
+ m ? i_start + name.size + m[1].size - 1 : -1
+ end
+
+ def field_i_range(name)
+ field_i_start(name)..field_i_end(name)
+ end
+
+ def field(line, name)
+ line[field_i_range(name)].strip
+ end
+
+ def [](id)
+ entries.find { |e| id == e['CONTAINER ID'] }
+ end
+ end
+
# Image
#
class Image
attr_accessor :name, :path
@@ -203,28 +257,58 @@
end # class Image
# Container
#
class Container
- attr_accessor :id, :long_id, :name, :image, :image_id, :ip, :ps, :ports, :params
+ attr_accessor :id
def initialize(id)
@id = id
- @ps = `docker ps | grep #{id}`
- container_inspect = `docker inspect #{id}`
- @params = JSON.parse(container_inspect).first
- @long_id = params['Id']
- @name = params['Name'].gsub('/', '')
- @image = params['Config']['Image']
- @image_id = params['Image']
- @ip = params['NetworkSettings']['IPAddress']
- port_maps = params['NetworkSettings']['Ports']
- @ports = port_maps.keys.map do |port|
+ end
+
+ def ps
+ Docker.ps[id] or fail "Failed to find ps info for #{id}"
+ end
+
+ def container_inspect
+ return @container_inspect if @container_inspect
+ # puts "Loading inspect for: #{ps}"
+ @container_inspect ||= JSON.parse(`docker inspect #{id}`).first
+ end
+
+ def long_id
+ container_inspect['Id']
+ end
+
+ def name
+ ps['NAMES']
+ # container_inspect['Name'].gsub('/', '')
+ end
+
+ def image
+ container_inspect['Config']['Image']
+ end
+
+ def image_id
+ container_inspect['Image']
+ end
+
+ def ip
+ container_inspect['NetworkSettings']['IPAddress']
+ end
+
+ def ports
+ port_maps = container_inspect['NetworkSettings']['Ports']
+ port_maps.keys.map do |port|
{ from: port, to: port_maps[port] }
end
end
+ def volumes
+ container_inspect['Volumes']
+ end
+
def open_ssh_session!(params = {}, command = nil)
ssh_flags = ['-oStrictHostKeyChecking=no']
if params['ssh_identity']
ssh_flags << "-i #{params['ssh_identity']}" if params['ssh_identity'].is_a?(String)
if params['ssh_identity'].is_a?(Array)
@@ -244,11 +328,11 @@
def clean!
self.class.clean_containers(name)
end
def uptime
- params['State'] && params['State']['StartedAt'] &&
- Time.now.utc - DateTime.parse(params['State']['StartedAt']).to_time.utc
+ container_inspect['State'] && container_inspect['State']['StartedAt'] &&
+ Time.now.utc - DateTime.parse(container_inspect['State']['StartedAt']).to_time.utc
end
def self.clean_containers(*names)
names.each do |name|
begin