class Cyclid::API::Plugins::LxdApi
LXD based transport
Attributes
exit_code[R]
exit_signal[R]
Public Class Methods
new(args = {})
click to toggle source
# File lib/cyclid/plugins/transport/lxdapi.rb, line 30 def initialize(args = {}) args.symbolize_keys! Cyclid.logger.debug "args=#{args}" # Container name & a log target are required return false unless args.include?(:host) && \ args.include?(:log) @name = args[:host] @log = args[:log] Cyclid.logger.debug "log=#{@log}" @config = load_lxd_config(Cyclid.config.plugins) @client = Hyperkit::Client.new(api_endpoint: @config[:api], verify_ssl: @config[:verify_ssl], client_cert: @config[:client_cert], client_key: @config[:client_key]) # Grab some data from the context Cyclid.logger.debug "lxdapi args=#{args.inspect}" ctx = args[:ctx] @base_env = { 'HOME' => ctx[:workspace], 'TERM' => 'xterm-mono' } @username = ctx[:username] end
Public Instance Methods
download(io, path)
click to toggle source
Copy a data from remote file to a local IO object
# File lib/cyclid/plugins/transport/lxdapi.rb, line 131 def download(io, path) @client.pull_file(@name, path, io) end
exec(cmd, args = {})
click to toggle source
Execute a command via. the LXD API
# File lib/cyclid/plugins/transport/lxdapi.rb, line 59 def exec(cmd, args = {}) sudo = args[:sudo] || false path = args[:path] command = build_command(cmd, sudo, path) Cyclid.logger.debug "command=#{command}" # Ensure some important variables are set, like HOME & TERM env = @env || {} env = env.merge @base_env # Run the command... rc = @client.execute_command(@name, command, environment: env, wait_for_websocket: true, interactive: true, sync: false) # ... and then connect a Websocket and read the output operation = rc[:id] ws_secret = rc[:metadata][:fds][:'0'] ws_url = "#{@config[:api]}/1.0/operations/#{operation}/websocket?secret=#{ws_secret}" closed = false log = @log WebSocket::Client::Simple.connect ws_url do |ws| ws.on :message do |msg| close if msg.data.empty? # Strip out any XTerm control characters and convert lint endings data = msg.data.encode('US-ASCII', invalid: :replace, undef: :replace, universal_newline: true) .squeeze("\n") .gsub(/\033\[(.?\d+\D?|\w+)/, '') log.write data end ws.on :open do Cyclid.logger.debug 'websocket opened' closed = false end ws.on :close do |e| Cyclid.logger.debug "websocket closed: #{e}" closed = true end ws.on :error do |e| Cyclid.logger.debug "websocket error: #{e}" end end # Wait until the Websocket thread has finished. loop do break if closed sleep 1 end # Get exit status status = @client.operation(operation) Cyclid.logger.debug "status=#{status.inspect}" @exit_code = status[:metadata][:return] @exit_code.zero? ? true : false end
upload(io, path)
click to toggle source
Copy data from a local IO object to a remote file via. the API
# File lib/cyclid/plugins/transport/lxdapi.rb, line 126 def upload(io, path) @client.push_file(io, @name, path) end
Private Instance Methods
build_command(cmd, sudo, path = nil)
click to toggle source
# File lib/cyclid/plugins/transport/lxdapi.rb, line 163 def build_command(cmd, sudo, path = nil) command = [] command << "cd #{path}" if path command << if @username == 'root' cmd elsif sudo "sudo -E -n $SHELL -l -c '#{cmd}'" else cmd end "sh -l -c '#{command.join(';')}'" end
load_lxd_config(config)
click to toggle source
Load the config for the LXD Builder plugin and set defaults if they're not in the config
# File lib/cyclid/plugins/transport/lxdapi.rb, line 142 def load_lxd_config(config) config.symbolize_keys! lxd_config = config[:lxd] || {} lxd_config.symbolize_keys! Cyclid.logger.debug "config=#{lxd_config}" raise 'the LXD API URL must be provided' \ unless lxd_config.key? :api lxd_config[:client_cert] = File.join(%w[/ etc cyclid lxd_client.crt]) \ unless lxd_config.key? :client_cert lxd_config[:client_key] = File.join(%w[/ etc cyclid lxd_client.key]) \ unless lxd_config.key? :client_key lxd_config[:verify_ssl] = false \ unless lxd_config.key? :verify_ssl lxd_config end