lib/nexussw/lxd/rest_api.rb in lxd-common-0.9.8 vs lib/nexussw/lxd/rest_api.rb in lxd-common-0.9.9
- old
+ new
@@ -1,24 +1,39 @@
-require 'nexussw/lxd/rest_api/connection'
-require 'nexussw/lxd/rest_api/errors'
-require 'shellwords'
+require "nexussw/lxd/rest_api/connection"
+require "nexussw/lxd/rest_api/errors"
+require "shellwords"
module NexusSW
module LXD
class RestAPI
def initialize(api_options)
@api_options = api_options
end
include RestAPI::Connection
+ def server_info
+ @server_info ||= LXD.symbolize_keys(get("/1.0"))[:metadata]
+ end
+
def create_container(container_name, options)
options, sync = parse_options options
- options[:config] = convert_bools(options[:config]) if options.key? :config
- handle_async post('/1.0/containers', create_source(options).merge(name: container_name)), sync
+ handle_async post("/1.0/containers", RestAPI.convert_bools(create_source(options).merge(name: container_name))), sync
end
+ def update_container(container_name, container_options)
+ if can_patch?
+ patch "/1.0/containers/#{container_name}", RestAPI.convert_bools(container_options)
+ else
+ data = container(container_name)[:metadata].select { |k, _| [:config, :devices, :profiles].include? k }
+ data[:config].merge! container_options[:config] if container_options.key? :config
+ data[:devices].merge! container_options[:devices] if container_options.key? :devices
+ data[:profiles] = container_options[:profiles] if container_options.key? :profiles
+ handle_async put("/1.0/containers/#{container_name}", RestAPI.convert_bools(data)), true
+ end
+ end
+
def execute_command(container_name, command, options)
options, sync = parse_options options
command = command.shellsplit if command.is_a? String
handle_async post("/1.0/containers/#{container_name}/exec", options.merge(command: command)), sync
end
@@ -33,16 +48,16 @@
delete "/1.0/containers/#{container_name}/logs/#{log_name}"
end
def start_container(container_name, options)
options, sync = parse_options options
- handle_async put("/1.0/containers/#{container_name}/state", options.merge(action: 'start')), sync
+ handle_async put("/1.0/containers/#{container_name}/state", options.merge(action: "start")), sync
end
def stop_container(container_name, options)
options, sync = parse_options options
- handle_async put("/1.0/containers/#{container_name}/state", options.merge(action: 'stop')), sync
+ handle_async put("/1.0/containers/#{container_name}/state", options.merge(action: "stop")), sync
end
def delete_container(container_name, options = {})
handle_async delete("/1.0/containers/#{container_name}"), options[:sync]
end
@@ -53,14 +68,14 @@
end
end
def write_file(container_name, path, options)
post "/1.0/containers/#{container_name}/files?path=#{path}", options[:content] do |req|
- req.headers['Content-Type'] = 'application/octet-stream'
- req.headers['X-LXD-uid'] = options[:uid] if options[:uid]
- req.headers['X-LXD-gid'] = options[:gid] if options[:gid]
- req.headers['X-LXD-mode'] = options[:file_mode] if options[:file_mode]
+ req.headers["Content-Type"] = "application/octet-stream"
+ req.headers["X-LXD-uid"] = options[:uid] if options[:uid]
+ req.headers["X-LXD-gid"] = options[:gid] if options[:gid]
+ req.headers["X-LXD-mode"] = options[:file_mode] if options[:file_mode]
end
end
# def push_file(local_path, container_name, remote_path)
# write_file container_name, remote_path, content: IO.binread(local_path)
@@ -73,34 +88,45 @@
def container_state(container_name)
get "/1.0/containers/#{container_name}/state"
end
def container(container_name)
- exceptkeys = %w(config expanded_config)
- get "/1.0/containers/#{container_name}" do |response|
- retval = JSON.parse(response.body)
- lift = retval['metadata'].select { |k, _| exceptkeys.include? k }
- retval['metadata'].delete_if { |k, _| exceptkeys.include? k }
- retval = LXD.symbolize_keys(retval)
- retval[:metadata][:config] = lift['config'] if lift.key? 'config'
- retval[:metadata][:expanded_config] = lift['expanded_config'] if lift.key? 'expanded_config'
- return retval
- end
+ get "/1.0/containers/#{container_name}"
end
def containers
- get('/1.0/containers')
+ get("/1.0/containers")
end
def wait_for_operation(operation_id)
get "/1.0/operations/#{operation_id}/wait"
end
+ def self.convert_bools(hash)
+ {}.tap do |retval|
+ hash.each do |k, v|
+ if [:ephemeral, :stateful].include? k
+ retval[k] = v
+ else
+ retval[k] = case v
+ when true then "true"
+ when false then "false"
+ else v.is_a?(Hash) && ([:config, :devices].include?(k)) ? convert_bools(v) : v
+ end
+ end
+ end
+ end
+ end
+
private
attr_reader :api_options
+ def can_patch?
+ server_info[:api_extensions].include? "patch"
+ end
+
def handle_async(data, sync)
return data if sync == false
wait_for_operation data[:metadata][:id]
end
@@ -110,23 +136,11 @@
end
def create_source(options)
moveprops = [:type, :alias, :fingerprint, :properties, :protocol, :server]
options.dup.tap do |retval|
- retval[:source] = { type: 'image', mode: 'pull' }.merge(retval.select { |k, _| moveprops.include? k }) unless retval.key? :source
+ retval[:source] = { type: "image", mode: "pull" }.merge(retval.select { |k, _| moveprops.include? k }) unless retval.key? :source
retval.delete_if { |k, _| moveprops.include? k }
- end
- end
-
- def convert_bools(hash)
- {}.tap do |retval|
- hash.each do |k, v|
- retval[k] = case v
- when true then 'true'
- when false then 'false'
- else v.is_a?(Hash) ? convert_bools(v) : v
- end
- end
end
end
end
end
end