lib/superhosting/docker_api.rb in superhosting-0.0.1 vs lib/superhosting/docker_api.rb in superhosting-0.0.2
- old
+ new
@@ -1,7 +1,12 @@
module Superhosting
class DockerApi
+ include Helper::Cmd
+ include Helper::Logger
+
+ AVAILABLE_DOCKER_OPTIONS = [:user, :cpu_period, :cpu_quota, :cpu_shares, :memory, :memory_swap]
+
def initialize(**kwargs)
@socket = kwargs[:socket] || '/var/run/docker.sock'
end
def raw_connection
@@ -10,22 +15,181 @@
def resp_if_success(resp)
JSON.load(resp.body) if resp.status == 200
end
+ def image_info(name)
+ resp_if_success raw_connection.request(method: :get, path: "/images/#{name}/json")
+ end
+
def container_info(name)
resp_if_success raw_connection.request(method: :get, path: "/containers/#{name}/json")
end
- def container_kill(name)
- resp_if_success raw_connection.request(method: :post, path: "/containers/#{name}/kill")
+ def container_list
+ resp_if_success raw_connection.request(method: :get, path: '/containers/json')
end
- def container_rm(name)
- resp_if_success raw_connection.request(method: :delete, path: "/containers/#{name}")
+ def container_kill!(name)
+ self.debug_operation(desc: { code: :container, data: { name: name } }) do |&blk|
+ self.with_dry_run do |dry_run|
+ self.storage.delete(name) if dry_run
+ resp_if_success raw_connection.request(method: :post, path: "/containers/#{name}/kill") unless dry_run
+ end
+ blk.call(code: :killed)
+ end
end
- def container_list
- resp_if_success raw_connection.request(method: :get, path: '/containers/json')
+ def container_rm!(name)
+ self.debug_operation(desc: { code: :container, data: { name: name } }) do |&blk|
+ self.with_dry_run do |dry_run|
+ self.storage.delete(name) if dry_run
+ resp_if_success raw_connection.request(method: :delete, path: "/containers/#{name}") unless dry_run
+ end
+ blk.call(code: :removed)
+ end
+ end
+
+ def container_stop!(name)
+ self.debug_operation(desc: { code: :container, data: { name: name } }) do |&blk|
+ self.with_dry_run do |dry_run|
+ self.storage[name] = 'exited' if dry_run
+ resp_if_success raw_connection.request(method: :post, path: "/containers/#{name}/stop") unless dry_run
+ end
+ blk.call(code: :stopped)
+ end
+ end
+
+ def container_start!(name)
+ self.debug_operation(desc: { code: :container, data: { name: name } }) do |&blk|
+ self.with_dry_run do |dry_run|
+ self.storage[name] = 'running' if dry_run
+ resp_if_success raw_connection.request(method: :post, path: "/containers/#{name}/start") unless dry_run
+ end
+ blk.call(code: :started)
+ end
+ end
+
+ def container_pause!(name)
+ self.debug_operation(desc: { code: :container, data: { name: name } }) do |&blk|
+ self.with_dry_run do |dry_run|
+ self.storage[name] = 'paused' if dry_run
+ resp_if_success raw_connection.request(method: :post, path: "/containers/#{name}/pause") unless dry_run
+ end
+ blk.call(code: :paused)
+ end
+ end
+
+ def container_unpause!(name)
+ self.debug_operation(desc: { code: :container, data: { name: name } }) do |&blk|
+ self.with_dry_run do |dry_run|
+ self.storage[name] = 'running' if dry_run
+ resp_if_success raw_connection.request(method: :post, path: "/containers/#{name}/unpause") unless dry_run
+ end
+ blk.call(code: :unpaused)
+ end
+ end
+
+ def container_restart!(name)
+ self.debug_operation(desc: { code: :container, data: { name: name } }) do |&blk|
+ self.with_dry_run do |dry_run|
+ resp_if_success raw_connection.request(method: :post, path: "/containers/#{name}/restart") unless dry_run
+ self.storage[name] = 'running' if dry_run
+ end
+ blk.call(code: :restarted)
+ end
+ end
+
+ def container_rm_inactive!(name)
+ self.container_rm!(name) if self.container_exists?(name) and !self.container_running?(name)
+ end
+
+ def container_status?(name, status)
+ self.with_dry_run do |dry_run|
+ return true if dry_run and self.storage[name] == status
+ resp = container_info(name)
+ if resp.nil?
+ false
+ else
+ resp['State'][status.capitalize]
+ end
+ end
+ end
+
+ def container_running?(name)
+ self.with_dry_run do |dry_run|
+ return true if dry_run and self.storage[name] == 'running'
+ resp = container_info(name)
+ if resp.nil?
+ false
+ else
+ resp['State']['Running'] and %w(Restarting Paused OOMKilled Dead).all? {|c| !resp['State'][c] }
+ end
+ end
+ end
+
+ def container_not_running?(name)
+ !container_running?(name)
+ end
+
+ def container_restarting?(name)
+ container_status?(name, 'restarting')
+ end
+
+ def container_paused?(name)
+ container_status?(name, 'paused')
+ end
+
+ def container_exited?(name)
+ container_status?(name, 'exited')
+ end
+
+ def container_dead?(name)
+ container_status?(name, 'dead')
+ end
+
+ def container_not_exists?(name)
+ !container_exists?(name)
+ end
+
+ def container_exists?(name)
+ self.with_dry_run do |dry_run|
+ return true if dry_run and self.storage.key? name
+ container_info(name).nil? ? false : true
+ end
+ end
+
+ def container_image?(name, image)
+ container = container_info(name)
+ image = image_info(image)
+
+ if container.nil? or image.nil?
+ false
+ else
+ container['Image'] == image['Id']
+ end
+ end
+
+ def container_run(name, options, image, command)
+ cmd = "docker run --detach --name #{name} #{options.join(' ')} #{image} #{command}"
+ self.debug_operation(desc: { code: :container, data: { name: name } }) do |&blk|
+ self.with_dry_run do |dry_run|
+ self.storage[name] = 'running' if dry_run
+ end
+
+ self.command!(cmd).tap do
+ blk.call(code: :added)
+ end
+ end
+ end
+
+ def grab_container_options(command_options)
+ options = []
+ AVAILABLE_DOCKER_OPTIONS.map do |k|
+ unless (value = command_options[k]).nil?
+ value.lines.each {|val| options << "--#{k.to_s.sub('_', '-')} #{val}" }
+ end
+ end
+ options
end
end
end