class Lunanode::API
Class for accessing the Lunanode
API
.
The class is instantiated by either passing it a JSON file containing the keys `api_id` and `api_key`, or specifying the ID and key directly:
api = Lunanode::API.new("credentials_file.json") api = Lunanode::API.new(api_id: "ABCDEFG", api_key: "HIJKLMNOP")
Once instantiated, action methods follow the example:
api.vm_list # no parameters api.vm_info(vm_id: "My-VM-ID") # required parameters api.image_list(region: "Toronto") # optional parameters
Required and optional arguments are specified in the method definitions, but can can be queried via {API.params_for}. They follow the API
specification atwiki.lunanode.com/index.php/API
Constants
- API_ENDPOINT
Class-level definitions
Attributes
Public Class Methods
Instantiate an API
object
@return [API] an API
instance.
@overload initialize(credentials_file)
Instantiate an API object from a credentials file. @param credentials_file[String,File] a JSON credentials file (which contains the keys `api_id` and `api_key`) @raise [JSON::ParserError] if the JSON file could not be read properly. @raise [KeyError] if any required key could not be found.
@overload initialize(api_id
: , api_key
: )
Instantiate an API object from an API ID and API Key. @param api_id[String] A LunaNode API ID @param api_key[String] A LunaNode API Key @raise [KeyError] if any required key could not be found.
# File lib/lunanode/api.rb, line 81 def initialize(*args, **options) credentials_file = args.compact.first.to_s if File.exist?(credentials_file) credentials_data = File.read(credentials_file) options = JSON.parse(credentials_data, symbolize_names: true) end @api_id = options.fetch(:api_id).to_s.dup.freeze @api_key = options.fetch(:api_key).to_s.dup.freeze @rest_client = RestClient::Resource.new( API_ENDPOINT, verify_ssl: OpenSSL::SSL::VERIFY_PEER ) end
Show parameter info for any {API} instance method.
The keys of the hash results denote the type of parameter:
-
:keyreq => Required keyword argument
-
:key => Optional keyword argument
-
:keyrest => Arbitrary additional keyword arguments
-
:req => Required positional argument
-
:opt => Optional positional argument
-
:rest => Arbitrary additional positional arguments
@param method_name The name of the API
method @return [Hash] information about the method parameters.
# File lib/lunanode/api.rb, line 44 def self.params_for(method_name) method_name = method_name.to_sym @params_for[method_name] ||= begin param_groups = instance_method(method_name).parameters.group_by(&:first) out = param_groups.map do |status, param_def| [status, param_def.map(&:last)] end out.to_h.each_value(&:freeze).freeze end end
Public Instance Methods
Send an arbitrary API
action without any parameter checks.
@param category The API
action category (i.e. dns, image, vm…) @param action The API
action name (i.e. create, list…) @param params Any parameters required for the action.
@return [Hash,Array,String] Response data from the API
action. @raise [APIError] If there was a problem with the action.
# File lib/lunanode/api.rb, line 110 def action(category, action, **params) resp = call_api("#{category}/#{action}/", params) raise APIError, resp[:error] unless resp.delete(:success) == "yes" if resp.size == 1 resp.values.first else resp end end
Display a string representation of the object without key information.
# File lib/lunanode/api.rb, line 96 def inspect "#<#{self.class.name}: api_id=#{api_id.inspect}>" end
Private Instance Methods
Create signed request data
# File lib/lunanode/api.rb, line 157 def auth_request_formdata(handler_path, params) req_msg = raw_request_message(params) nonce = gen_nonce signature = gen_signature(handler_path, req_msg, nonce) { req: req_msg, signature: signature, nonce: nonce, } end
Make an API
call and return response.
# File lib/lunanode/api.rb, line 126 def call_api(handler_path, params) req_url = "#{rest_client.url}#{handler_path}" req_formdata = auth_request_formdata(handler_path, clean_params(params)) if $DEBUG STDERR.puts "call_api()\n" + JSON.pretty_generate( path: req_url, req: JSON.parse(req_formdata[:req]), signature: req_formdata[:signature], nonce: req_formdata[:nonce] ) end response = rest_client[handler_path].post(req_formdata) JSON.parse(response, symbolize_names: true) rescue RestClient::Exception => err err.message += "\n Request Path: #{req_url}" \ "\n Request Data: #{req_formdata}" raise err end
Clean empty request parameters
# File lib/lunanode/api.rb, line 148 def clean_params(params) params.each_with_object({}) do |(param, value), acc| next if param.nil? || value.nil? next unless param.respond_to?(:to_sym) && value.respond_to?(:to_s) acc[param.to_sym] = value.to_s end end
Generate nonce for request
# File lib/lunanode/api.rb, line 176 def gen_nonce Time.now.utc.to_i.to_s end
Generate signature for request
# File lib/lunanode/api.rb, line 181 def gen_signature(handler_path, req_msg, nonce) message = "#{handler_path}|#{req_msg}|#{nonce}" OpenSSL::HMAC.hexdigest("SHA512", api_key, message) end
Generate raw, unsigned request message.
# File lib/lunanode/api.rb, line 169 def raw_request_message(params) params[:api_id] = api_id params[:api_partialkey] = api_key.slice(0, 64) JSON.generate(params) end