module NexusSW::LXD::Transport::Mixins::Rest

Attributes

api[R]
config[R]
container_name[R]
rest_endpoint[R]

Public Class Methods

new(container_name, config = {}) click to toggle source
# File lib/nexussw/lxd/transport/mixins/rest.rb, line 14
def initialize(container_name, config = {})
  @container_name = container_name
  @config = config
  @rest_endpoint = config[:rest_endpoint]
  @driver_options = config[:driver_options]
  @api = config[:connection]
  raise "The rest transport requires the following keys: { :connection, :driver_options, :rest_endpoint }" unless @rest_endpoint && @api && @driver_options
end

Public Instance Methods

download_file(path, local_path) click to toggle source
# File lib/nexussw/lxd/transport/mixins/rest.rb, line 133
def download_file(path, local_path)
  api.pull_file container_name, path, local_path
end
execute_chunked(command, options = {}) { |active| ... } click to toggle source
# File lib/nexussw/lxd/transport/mixins/rest.rb, line 64
def execute_chunked(command, options = {}, &block)
  opid = nil
  backchannel = nil
  getlogs = false
  command = runas_command(command, options)
  if block_given? && (options[:capture] || !config[:info][:api_extensions].include?("container_exec_recording"))
    apiopts = { 'wait-for-websocket': true, interactive: false, sync: false }
    apiopts[:interactive] = true if options[:capture] == :interactive
    retval = api.execute_command(container_name, command, apiopts)[:metadata]
    opid = retval[:id]
    backchannel = options[:capture] == :interactive ? ws_connect(opid, retval[:metadata][:fds]) : ws_connect(opid, retval[:metadata][:fds], &block)

    # patch for interactive session
    if options[:capture] == :interactive
      return Helpers::ExecuteMixin::InteractiveResult.new(command, options, StdinStub.pipe(backchannel.waitlist[:'0']), backchannel).tap do |active|
        backchannel.callback = proc do |stdout|
          active.send_output stdout
        end
        yield active
        backchannel.exit if backchannel.respond_to? :exit
        retval = api.wait_for_operation opid
        active.exitstatus = retval[:metadata][:return].to_i
      end
    end
  elsif block_given? && config[:info][:api_extensions].include?("container_exec_recording")
    getlogs = true
    retval = api.execute_command(container_name, command, 'record-output': true, interactive: false, sync: false)
    opid = retval[:metadata][:id]
  else
    opid = api.execute_command(container_name, command, sync: false)[:metadata][:id]
  end
  LXD.with_timeout_and_retries({ timeout: 0 }.merge(options)) do
    begin
      retval = api.wait_for_operation(opid)[:metadata]
      backchannel.waitlist[:'0'].close if backchannel.respond_to? :waitlist
      backchannel.waitlist[:control].close if backchannel.respond_to? :waitlist
      backchannel.join if backchannel.respond_to? :join
      if getlogs
        begin
          stdout_log = retval[:metadata][:output][:'1'].split("/").last
          stderr_log = retval[:metadata][:output][:'2'].split("/").last
          stdout = api.log container_name, stdout_log
          stderr = api.log container_name, stderr_log
          yield stdout, stderr

          api.delete_log container_name, stdout_log
          api.delete_log container_name, stderr_log
        end
      end
      return Helpers::ExecuteMixin::ExecuteResult.new command, options, retval[:metadata][:return].to_i
    rescue Faraday::TimeoutError => e
      raise Timeout::Retry.new e # rubocop:disable Style/RaiseArgs
    end
  end
end
read_file(path) click to toggle source

empty '' instead of an exception is a chef-provisioning expectation - at this level we'll let the exception propagate

# File lib/nexussw/lxd/transport/mixins/rest.rb, line 121
def read_file(path)
  api.read_file container_name, path
end
upload_file(local_path, path, options = {}) click to toggle source
# File lib/nexussw/lxd/transport/mixins/rest.rb, line 137
def upload_file(local_path, path, options = {})
  # return api.push_file(local_path, container_name, path)
  write_file(path, IO.binread(local_path), options)
end
write_file(path, content, options = {}) click to toggle source
# File lib/nexussw/lxd/transport/mixins/rest.rb, line 125
def write_file(path, content, options = {})
  options = options.merge content: content
  options[:uid] ||= uid if uid
  options[:gid] ||= gid if gid
  options[:file_mode] ||= file_mode if file_mode
  api.write_file container_name, path, options
end

Protected Instance Methods

ws_connect(opid, endpoints, &block) click to toggle source
# File lib/nexussw/lxd/transport/mixins/rest.rb, line 233
def ws_connect(opid, endpoints, &block)
  # NIO::WebSocket.log_traffic = true
  verify_ssl = OpenSSL::SSL::VERIFY_NONE if @driver_options[:verify_ssl] == false
  ws_options = { ssl_context: { verify_mode: verify_ssl } } unless verify_ssl.nil?
  ws_options ||= {}
  baseurl = rest_endpoint.sub(%r{^http([s]?://)}, 'ws\1')
  baseurl += "/" unless baseurl.end_with? "/"
  baseurl += "1.0/operations/#{opid}/websocket?secret="

  WSController.new ws_options, baseurl, endpoints, &block
end