lib/rake/proxmox/proxmox_api.rb in rake-proxmox-0.3.0 vs lib/rake/proxmox/proxmox_api.rb in rake-proxmox-0.5.0

- old
+ new

@@ -1,7 +1,10 @@ -require 'rest_client' +require 'faraday' +require 'faraday_middleware' +require 'httpclient' require 'json' +require 'logger' module Rake module Proxmox # ProxmoxApi adopted from https://github.com/nledez/proxmox # rubocop:disable Metrics/ClassLength @@ -22,20 +25,47 @@ # Proxmox::Proxmox.new('https://the-proxmox-server:8006/api2/json/', # 'node', 'root', 'secret', 'pam', # {verify_ssl: false}) # # rubocop:disable Metrics/ParameterLists + # rubocop:disable Metrics/AbcSize def initialize(pve_cluster, node, username, password, realm, - ssl_options = {}) + ssl_options = {}, logger = nil) @pve_cluster = pve_cluster @node = node @username = username @password = password @realm = realm @ssl_options = ssl_options @connection_status = 'error' - @site = RestClient::Resource.new(@pve_cluster, @ssl_options) + use_default_logger = logger.nil? + logger ||= Logger.new STDERR + # set default loglevel + logger.level = Logger::WARN if use_default_logger + user_agent = "rake-proxmox #{Rake::Proxmox::VERSION}" + @site = Faraday.new(url: @pve_cluster, headers: { + user_agent: user_agent + }) do |conn| + # POST/PUT params encoders: + conn.request :multipart + conn.request :url_encoded + + # allow Faraday to retry request + conn.request :retry, max: 3, interval: 0.05, + interval_randomness: 0.5, backoff_factor: 2, + exceptions: %w[HTTPClient::KeepAliveDisconnected + Timeout::Error] + + conn.response :json, content_type: /\bjson$/ + conn.response :logger, logger do |log| + log.filter(/(Csrfpreventiontoken:)\s+(.*)$/, '\1 "[REMOVED]"') + log.filter(/(Cookie:)\s+(.*)$/, '\1 "[REMOVED]"') + end + + # Last middleware must be the adapter: + conn.adapter :httpclient + end @auth_params = create_ticket end def get(path, args = {}) http_action_get(path, args) @@ -472,32 +502,31 @@ # upload lxc template def upload_template(filename, node = @node, storage = 'local') "Template #{filename} does not exist locally" unless File.file? filename data = { content: 'vztmpl', - filename: File.new(filename) + filename: Faraday::UploadIO.new(filename, 'application/gzip') } http_action_post("nodes/#{node}/storage/#{storage}/upload", data) end private # Methods manages auth def create_ticket post_param = { username: @username, realm: @realm, password: @password } - @site['access/ticket'].post post_param do |resp, _req, _res, &_block| - if resp.code == 200 - extract_ticket resp - else - @connection_status = 'error' - end + resp = @site.post('access/ticket', post_param) + if resp.success? + extract_ticket resp + else + @connection_status = 'error' end end # Method create ticket def extract_ticket(response) - data = JSON.parse(response.body) + data = response.body ticket = data['data']['ticket'] csrf_prevention_token = data['data']['CSRFPreventionToken'] unless ticket.nil? token = 'PVEAuthCookie=' + ticket.gsub!(/:/, '%3A').gsub!(/=/, '%3D') end @@ -506,43 +535,55 @@ CSRFPreventionToken: csrf_prevention_token, cookie: token } end + def json_decode(response) + if response.headers.include?('Content-Type') && + response.headers['Content-Type'] =~ /\bjson/ + response.body + else + JSON.parse(response.body) + end + end + # Extract data or return error def check_response(response) - if response.code == 200 - JSON.parse(response.body)['data'] + if response.success? + json_decode(response)['data'] else - 'NOK: error code = ' + response.code.to_s \ + 'NOK: error code = ' + response.status.to_s \ + 'data = ' + response.body + "\n" end end # Methods manage http dialogs - def http_action_post(url, data = {}) - # print "POST #{url}\n#{data}\n" - @site[url].post data, @auth_params do |resp, _req, _res, &_block| - check_response resp + def http_action_post(url, payload = {}) + resp = @site.post(url, payload) do |req| + req.headers.merge!(@auth_params) end + check_response resp end def http_action_put(url, data = {}) - @site[url].put data, @auth_params do |resp, _req, _res, &_block| - check_response resp + resp = @site.put(url, data) do |req| + req.headers.merge!(@auth_params) end + check_response resp end def http_action_get(url, data = {}) - @site[url].get @auth_params.merge(data) do |resp, _req, _res, &_block| - check_response resp + resp = @site.get(url, data) do |req| + req.headers.merge!(@auth_params) end + check_response resp end def http_action_delete(url) - @site[url].delete @auth_params do |resp, _req, _res, &_block| - check_response resp + resp = @site.delete(url) do |req| + req.headers.merge!(@auth_params) end + check_response resp end end end end