lunanode 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +16 -0
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/.rubocop.yml +94 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +11 -0
- data/.yardopts +1 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +50 -0
- data/Rakefile +19 -0
- data/bin/console +8 -0
- data/bin/setup +8 -0
- data/lib/lunanode.rb +12 -0
- data/lib/lunanode/action_generator.rb +105 -0
- data/lib/lunanode/api.rb +172 -0
- data/lib/lunanode/api_actions.rb +41 -0
- data/lib/lunanode/api_actions/default/dns.rb +55 -0
- data/lib/lunanode/api_actions/default/email.rb +59 -0
- data/lib/lunanode/api_actions/default/floating.rb +19 -0
- data/lib/lunanode/api_actions/default/image.rb +31 -0
- data/lib/lunanode/api_actions/default/lb.rb +35 -0
- data/lib/lunanode/api_actions/default/monitor.rb +47 -0
- data/lib/lunanode/api_actions/default/network.rb +19 -0
- data/lib/lunanode/api_actions/default/plan.rb +11 -0
- data/lib/lunanode/api_actions/default/region.rb +11 -0
- data/lib/lunanode/api_actions/default/script.rb +11 -0
- data/lib/lunanode/api_actions/default/securitygroup.rb +35 -0
- data/lib/lunanode/api_actions/default/vm.rb +99 -0
- data/lib/lunanode/api_actions/default/volume.rb +47 -0
- data/lib/lunanode/api_actions/dns.rb +10 -0
- data/lib/lunanode/api_actions/email.rb +10 -0
- data/lib/lunanode/api_actions/floating.rb +10 -0
- data/lib/lunanode/api_actions/image.rb +17 -0
- data/lib/lunanode/api_actions/lb.rb +10 -0
- data/lib/lunanode/api_actions/monitor.rb +10 -0
- data/lib/lunanode/api_actions/network.rb +10 -0
- data/lib/lunanode/api_actions/plan.rb +10 -0
- data/lib/lunanode/api_actions/region.rb +10 -0
- data/lib/lunanode/api_actions/script.rb +10 -0
- data/lib/lunanode/api_actions/securitygroup.rb +10 -0
- data/lib/lunanode/api_actions/vm.rb +10 -0
- data/lib/lunanode/api_actions/volume.rb +10 -0
- data/lib/lunanode/api_error.rb +5 -0
- data/lib/lunanode/version.rb +4 -0
- data/lunanode.gemspec +33 -0
- data/lunanode_api_def.yaml +391 -0
- metadata +191 -0
data/lib/lunanode/api.rb
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
require "rest-client"
|
5
|
+
|
6
|
+
module Lunanode
|
7
|
+
# Class for accessing the Lunanode API.
|
8
|
+
#
|
9
|
+
# The class is instantiated by either passing it a JSON file containing
|
10
|
+
# the keys `api_id` and `api_key`, or specifying the ID and key directly:
|
11
|
+
# api = Lunanode::API.new("credentials_file.json")
|
12
|
+
# api = Lunanode::API.new(api_id: "ABCDEFG", api_key: "HIJKLMNOP")
|
13
|
+
#
|
14
|
+
# Once instantiated, action methods follow the example:
|
15
|
+
# api.vm_list # no parameters
|
16
|
+
# api.vm_info(vm_id: "My-VM-ID") # required parameters
|
17
|
+
# api.image_list(region: "Toronto") # optional parameters
|
18
|
+
#
|
19
|
+
# Required and optional arguments are specified in the method definitions,
|
20
|
+
# but can can be queried via {API.params_for}. They follow the API
|
21
|
+
# specification athttps://wiki.lunanode.com/index.php/API
|
22
|
+
#
|
23
|
+
class API
|
24
|
+
#
|
25
|
+
# Class-level definitions
|
26
|
+
#
|
27
|
+
|
28
|
+
API_ENDPOINT = "https://dynamic.lunanode.com/api/".freeze
|
29
|
+
@params_for = {}
|
30
|
+
|
31
|
+
# Show parameter info for any API method.
|
32
|
+
#
|
33
|
+
# @param method_name[#to_sym] The name of the API method
|
34
|
+
# @return [Hash] information about the method parameters
|
35
|
+
#
|
36
|
+
def self.params_for(method_name)
|
37
|
+
@params_for[method_name] ||= begin
|
38
|
+
method_name = method_name.to_sym
|
39
|
+
param_groups = instance_method(method_name).parameters.group_by(&:first)
|
40
|
+
out = {
|
41
|
+
required: param_groups[:keyreq] && param_group[:keyreq].map(&:last),
|
42
|
+
optional: param_groups[:key] && param_groups[:key].map(&:last),
|
43
|
+
additional: param_groups.key?(:keyrest),
|
44
|
+
}
|
45
|
+
out.each do |k, v|
|
46
|
+
if v
|
47
|
+
v.freeze
|
48
|
+
else
|
49
|
+
out.delete(k)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
out.freeze
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# Instance-level definitions
|
58
|
+
#
|
59
|
+
|
60
|
+
include APIActions
|
61
|
+
attr_reader :api_id
|
62
|
+
|
63
|
+
# @overload initialize(credentials_file)
|
64
|
+
# Instantiate an API object from a credentials file.
|
65
|
+
# @param credentials_file[IO,String] a JSON credentials file
|
66
|
+
# (which contains the keys `api_id` and `api_key`)
|
67
|
+
#
|
68
|
+
# @overload initialize(api_id: nil, api_key: nil)
|
69
|
+
# Instantiate an API object from an API ID and API Key.
|
70
|
+
# @param api_id[String] A LunaNode API ID
|
71
|
+
# @param api_key[String] A LunaNode API Key
|
72
|
+
#
|
73
|
+
def initialize(credentials_file = nil, api_id: nil, api_key: nil)
|
74
|
+
if !credentials_file.nil? && File.exist?(credentials_file)
|
75
|
+
credentials_data = File.read(credentials_file)
|
76
|
+
credentials = JSON.parse(credentials_data, symbolize_names: true)
|
77
|
+
@api_id = credentials[:api_id]
|
78
|
+
@api_key = credentials[:api_key]
|
79
|
+
else
|
80
|
+
@api_id = api_id
|
81
|
+
@api_key = api_key
|
82
|
+
end
|
83
|
+
@api_id = @api_id.to_s.freeze
|
84
|
+
@api_key = @api_key.to_s.freeze
|
85
|
+
@rest_client = RestClient::Resource.new(
|
86
|
+
API_ENDPOINT,
|
87
|
+
verify_ssl: OpenSSL::SSL::VERIFY_PEER
|
88
|
+
)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Display a string representation of the object without key information.
|
92
|
+
def inspect
|
93
|
+
"#<#{self.class.name}: api_id=#{api_id.inspect}>"
|
94
|
+
end
|
95
|
+
alias to_s inspect
|
96
|
+
|
97
|
+
# Send an arbitrary API action without any parameter checks.
|
98
|
+
#
|
99
|
+
# @param category[#to_sym] The API action category (i.e. dns, image, vm...)
|
100
|
+
# @param action[#to_sym] The API action name (i.e. create, list...)
|
101
|
+
# @param params[Hash] Any parameters required for the action.
|
102
|
+
#
|
103
|
+
# @return [Hash,Array,String] Response data from the API action.
|
104
|
+
# @raise [APIError] If there was a problem with the action.
|
105
|
+
#
|
106
|
+
def action(category, action, **params)
|
107
|
+
resp = call_api("#{category}/#{action}/", params)
|
108
|
+
raise APIError, %("#{resp[:error]}") unless resp[:success] == "yes"
|
109
|
+
resp.delete(:success)
|
110
|
+
|
111
|
+
if resp.size == 1
|
112
|
+
resp.values.first
|
113
|
+
else
|
114
|
+
resp
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
attr_reader :api_key, :rest_client
|
121
|
+
|
122
|
+
# Make an API call and return response.
|
123
|
+
def call_api(handler_path, params)
|
124
|
+
req_formdata = auth_request_formdata(handler_path, clean_params(params))
|
125
|
+
JSON.parse(rest_client[handler_path].post(req_formdata),
|
126
|
+
symbolize_names: true)
|
127
|
+
rescue RestClient::Exception => err
|
128
|
+
err.message += "\n Request Path: #{rest_client.url}#{handler_path}" \
|
129
|
+
"\n Request Data: #{req_data}"
|
130
|
+
raise err
|
131
|
+
end
|
132
|
+
|
133
|
+
# Clean empty request parameters
|
134
|
+
def clean_params(params)
|
135
|
+
params.each_with_object({}) do |(k, v), acc|
|
136
|
+
if k && k.respond_to?(:to_sym) && v && v.respond_to?(:to_s)
|
137
|
+
acc[k.to_sym] = v.to_s
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Create signed request data
|
143
|
+
def auth_request_formdata(handler_path, params)
|
144
|
+
req_msg = raw_request_message(params)
|
145
|
+
nonce = gen_nonce
|
146
|
+
signature = gen_signature(handler_path, req_msg, nonce)
|
147
|
+
{
|
148
|
+
req: req_msg,
|
149
|
+
signature: signature,
|
150
|
+
nonce: nonce,
|
151
|
+
}
|
152
|
+
end
|
153
|
+
|
154
|
+
# Generate raw, unsigned request message.
|
155
|
+
def raw_request_message(params)
|
156
|
+
params[:api_id] = api_id
|
157
|
+
params[:api_partialkey] = api_key.slice(0, 64)
|
158
|
+
params.to_json
|
159
|
+
end
|
160
|
+
|
161
|
+
# Generate nonce for request
|
162
|
+
def gen_nonce
|
163
|
+
Time.now.utc.to_i.to_s
|
164
|
+
end
|
165
|
+
|
166
|
+
# Generate signature for request
|
167
|
+
def gen_signature(handler_path, req_msg, nonce)
|
168
|
+
message = "#{handler_path}|#{req_msg}|#{nonce}"
|
169
|
+
OpenSSL::HMAC.hexdigest("SHA512", api_key, message)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "lunanode/api_actions/dns"
|
4
|
+
require "lunanode/api_actions/email"
|
5
|
+
require "lunanode/api_actions/floating"
|
6
|
+
require "lunanode/api_actions/image"
|
7
|
+
require "lunanode/api_actions/lb"
|
8
|
+
require "lunanode/api_actions/monitor"
|
9
|
+
require "lunanode/api_actions/network"
|
10
|
+
require "lunanode/api_actions/plan"
|
11
|
+
require "lunanode/api_actions/region"
|
12
|
+
require "lunanode/api_actions/script"
|
13
|
+
require "lunanode/api_actions/securitygroup"
|
14
|
+
require "lunanode/api_actions/vm"
|
15
|
+
require "lunanode/api_actions/volume"
|
16
|
+
|
17
|
+
module Lunanode
|
18
|
+
# Module containing all API action methods included from various component
|
19
|
+
# modules.
|
20
|
+
#
|
21
|
+
# Standard API action methods were automatically generated from a datafile to
|
22
|
+
# specifying all required and optional parameters as keyword arguments.
|
23
|
+
#
|
24
|
+
# See https://wiki.lunanode.com/index.php/API for more details on the
|
25
|
+
# individual actions and parameters.
|
26
|
+
module APIActions
|
27
|
+
# Modules are included in reverse order so that YARD shows them correctly.
|
28
|
+
include Volume
|
29
|
+
include VM
|
30
|
+
include Securitygroup
|
31
|
+
include Script
|
32
|
+
include Plan
|
33
|
+
include Network
|
34
|
+
include Monitor
|
35
|
+
include LB
|
36
|
+
include Image
|
37
|
+
include Floating
|
38
|
+
include Email
|
39
|
+
include DNS
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lunanode
|
4
|
+
module APIActions
|
5
|
+
module DNS
|
6
|
+
def dns_list
|
7
|
+
action(:dns, :list)
|
8
|
+
end
|
9
|
+
|
10
|
+
def dns_set(ip:, hostname:)
|
11
|
+
action(:dns, :set, ip: ip, hostname: hostname)
|
12
|
+
end
|
13
|
+
|
14
|
+
def dns_zone_list
|
15
|
+
action(:dns, :zone_list)
|
16
|
+
end
|
17
|
+
|
18
|
+
def dns_zone_add(origin:, ttl: nil)
|
19
|
+
action(:dns, :zone_add, origin: origin, ttl: ttl)
|
20
|
+
end
|
21
|
+
|
22
|
+
def dns_zone_remove(zone_id:)
|
23
|
+
action(:dns, :zone_remove, zone_id: zone_id)
|
24
|
+
end
|
25
|
+
|
26
|
+
def dns_record_list(zone_id:)
|
27
|
+
action(:dns, :record_list, zone_id: zone_id)
|
28
|
+
end
|
29
|
+
|
30
|
+
def dns_record_add(zone_id:, name:, data:, ttl:, type:)
|
31
|
+
action(:dns, :record_add, zone_id: zone_id, name: name, data: data, ttl: ttl, type: type)
|
32
|
+
end
|
33
|
+
|
34
|
+
def dns_record_remove(record_id:)
|
35
|
+
action(:dns, :record_remove, record_id: record_id)
|
36
|
+
end
|
37
|
+
|
38
|
+
def dns_dyn_list
|
39
|
+
action(:dns, :dyn_list)
|
40
|
+
end
|
41
|
+
|
42
|
+
def dns_dyn_add(name:, ip:)
|
43
|
+
action(:dns, :dyn_add, name: name, ip: ip)
|
44
|
+
end
|
45
|
+
|
46
|
+
def dns_dyn_update(dyn_id:, name:, ip:)
|
47
|
+
action(:dns, :dyn_update, dyn_id: dyn_id, name: name, ip: ip)
|
48
|
+
end
|
49
|
+
|
50
|
+
def dns_dyn_remove(dyn_id:)
|
51
|
+
action(:dns, :dyn_remove, dyn_id: dyn_id)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lunanode
|
4
|
+
module APIActions
|
5
|
+
module Email
|
6
|
+
def email_usage
|
7
|
+
action(:email, :usage)
|
8
|
+
end
|
9
|
+
|
10
|
+
def email_domain_list
|
11
|
+
action(:email, :domain_list)
|
12
|
+
end
|
13
|
+
|
14
|
+
def email_domain_add(name:)
|
15
|
+
action(:email, :domain_add, name: name)
|
16
|
+
end
|
17
|
+
|
18
|
+
def email_domain_remove(domain_id:)
|
19
|
+
action(:email, :domain_remove, domain_id: domain_id)
|
20
|
+
end
|
21
|
+
|
22
|
+
def email_domain_dkim_set(domain_id:, selector:, private_key:)
|
23
|
+
action(:email, :domain_dkim_set, domain_id: domain_id, selector: selector, private_key: private_key)
|
24
|
+
end
|
25
|
+
|
26
|
+
def email_domain_dkim_unset(domain_id:)
|
27
|
+
action(:email, :domain_dkim_unset, domain_id: domain_id)
|
28
|
+
end
|
29
|
+
|
30
|
+
def email_user_list(domain_id:)
|
31
|
+
action(:email, :user_list, domain_id: domain_id)
|
32
|
+
end
|
33
|
+
|
34
|
+
def email_user_add(domain_id:, username:, password:)
|
35
|
+
action(:email, :user_add, domain_id: domain_id, username: username, password: password)
|
36
|
+
end
|
37
|
+
|
38
|
+
def email_user_set_password(domain_id:, user_id:, password:)
|
39
|
+
action(:email, :user_set_password, domain_id: domain_id, user_id: user_id, password: password)
|
40
|
+
end
|
41
|
+
|
42
|
+
def email_user_remove(domain_id:, user_id:)
|
43
|
+
action(:email, :user_remove, domain_id: domain_id, user_id: user_id)
|
44
|
+
end
|
45
|
+
|
46
|
+
def email_alias_list(domain_id:)
|
47
|
+
action(:email, :alias_list, domain_id: domain_id)
|
48
|
+
end
|
49
|
+
|
50
|
+
def email_alias_add(domain_id:, name:, target:)
|
51
|
+
action(:email, :alias_add, domain_id: domain_id, name: name, target: target)
|
52
|
+
end
|
53
|
+
|
54
|
+
def email_alias_remove(domain_id:, alias_id:)
|
55
|
+
action(:email, :alias_remove, domain_id: domain_id, alias_id: alias_id)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lunanode
|
4
|
+
module APIActions
|
5
|
+
module Floating
|
6
|
+
def floating_list
|
7
|
+
action(:floating, :list)
|
8
|
+
end
|
9
|
+
|
10
|
+
def floating_add(region:)
|
11
|
+
action(:floating, :add, region: region)
|
12
|
+
end
|
13
|
+
|
14
|
+
def floating_delete(region:, ip:)
|
15
|
+
action(:floating, :delete, region: region, ip: ip)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lunanode
|
4
|
+
module APIActions
|
5
|
+
module Image
|
6
|
+
def image_list(region: nil)
|
7
|
+
action(:image, :list, region: region)
|
8
|
+
end
|
9
|
+
|
10
|
+
def image_delete(image_id:)
|
11
|
+
action(:image, :delete, image_id: image_id)
|
12
|
+
end
|
13
|
+
|
14
|
+
def image_details(image_id:)
|
15
|
+
action(:image, :details, image_id: image_id)
|
16
|
+
end
|
17
|
+
|
18
|
+
def image_replicate(image_id:, region:)
|
19
|
+
action(:image, :replicate, image_id: image_id, region: region)
|
20
|
+
end
|
21
|
+
|
22
|
+
def image_fetch(region:, name:, location:, format:, virtio: nil)
|
23
|
+
action(:image, :fetch, region: region, name: name, location: location, format: format, virtio: virtio)
|
24
|
+
end
|
25
|
+
|
26
|
+
def image_retrieve(image_id:)
|
27
|
+
action(:image, :retrieve, image_id: image_id)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lunanode
|
4
|
+
module APIActions
|
5
|
+
module LB
|
6
|
+
def lb_list(region:, net_id: nil)
|
7
|
+
action(:lb, :list, region: region, net_id: net_id)
|
8
|
+
end
|
9
|
+
|
10
|
+
def lb_create(region:, net_id:, name:, method:, protocol:, connection_limit:, port:)
|
11
|
+
action(:lb, :create, region: region, net_id: net_id, name: name, method: method, protocol: protocol, connection_limit: connection_limit, port: port)
|
12
|
+
end
|
13
|
+
|
14
|
+
def lb_delete(region:, lb_id:)
|
15
|
+
action(:lb, :delete, region: region, lb_id: lb_id)
|
16
|
+
end
|
17
|
+
|
18
|
+
def lb_info(region:, lb_id:)
|
19
|
+
action(:lb, :info, region: region, lb_id: lb_id)
|
20
|
+
end
|
21
|
+
|
22
|
+
def lb_member_add(region:, lb_id:, ip:, port:)
|
23
|
+
action(:lb, :member_add, region: region, lb_id: lb_id, ip: ip, port: port)
|
24
|
+
end
|
25
|
+
|
26
|
+
def lb_member_remove(region:, lb_id:, member_id:)
|
27
|
+
action(:lb, :member_remove, region: region, lb_id: lb_id, member_id: member_id)
|
28
|
+
end
|
29
|
+
|
30
|
+
def lb_associate(region:, lb_id:, ip:)
|
31
|
+
action(:lb, :associate, region: region, lb_id: lb_id, ip: ip)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lunanode
|
4
|
+
module APIActions
|
5
|
+
module Monitor
|
6
|
+
def monitor_check_list
|
7
|
+
action(:monitor, :check_list)
|
8
|
+
end
|
9
|
+
|
10
|
+
def monitor_check_types
|
11
|
+
action(:monitor, :check_types)
|
12
|
+
end
|
13
|
+
|
14
|
+
def monitor_check_add(name:, type:, fail_count:, success_count:, check_interval:, **from_check_type)
|
15
|
+
action(:monitor, :check_add, name: name, type: type, fail_count: fail_count, success_count: success_count, check_interval: check_interval, **from_check_type)
|
16
|
+
end
|
17
|
+
|
18
|
+
def monitor_check_remove(check_id:)
|
19
|
+
action(:monitor, :check_remove, check_id: check_id)
|
20
|
+
end
|
21
|
+
|
22
|
+
def monitor_contact_list
|
23
|
+
action(:monitor, :contact_list)
|
24
|
+
end
|
25
|
+
|
26
|
+
def monitor_contact_add
|
27
|
+
action(:monitor, :contact_add)
|
28
|
+
end
|
29
|
+
|
30
|
+
def monitor_contact_remove(type:, rel:)
|
31
|
+
action(:monitor, :contact_remove, type: type, rel: rel)
|
32
|
+
end
|
33
|
+
|
34
|
+
def monitor_alert_list(check_id:)
|
35
|
+
action(:monitor, :alert_list, check_id: check_id)
|
36
|
+
end
|
37
|
+
|
38
|
+
def monitor_alert_add(check_id:, contact_id:)
|
39
|
+
action(:monitor, :alert_add, check_id: check_id, contact_id: contact_id)
|
40
|
+
end
|
41
|
+
|
42
|
+
def monitor_alert_remove(alert_id:)
|
43
|
+
action(:monitor, :alert_remove, alert_id: alert_id)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|