tortoiselabs 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/tortoiselabs.rb +7 -0
- data/lib/tortoiselabs/billing.rb +58 -0
- data/lib/tortoiselabs/client.rb +37 -0
- data/lib/tortoiselabs/dns.rb +94 -0
- data/lib/tortoiselabs/vps.rb +230 -0
- metadata +62 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e136ce22e408526d7c3b1943109df33754828a51
|
4
|
+
data.tar.gz: 034993dbd882ec9335b1cdd8305c3d2befa3353b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5c26e7690ab29d6c04eb5c283b2cddf807fa6f15329cc04abd865204d66fa17bdaf5e38c873749440d8b81d84c898bff2b640c759045a78798e4567d47148cb6
|
7
|
+
data.tar.gz: dcae0f8796209cce5dc8bc22d2be75efc9cb95265670d7e381f1520e71cdefffea5a555e627ebf94df9218ef5829cd3f1cf7a2ae7118604848a45a3ee6377e38
|
data/lib/tortoiselabs.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
module TortoiseLabs
|
2
|
+
class Invoice
|
3
|
+
attr_reader :items, :creation_ts, :payment_ts, :total, :user, :id
|
4
|
+
|
5
|
+
def initialize(ihash)
|
6
|
+
@creation_ts, @total = ihash["creation_ts"], ihash["total"]
|
7
|
+
@payment_ts, @user = ihash["payment_ts"], ihash["user"]
|
8
|
+
@id = ihash["invoice"]
|
9
|
+
@items = Array.new
|
10
|
+
|
11
|
+
ihash["items"].each do |itemhash|
|
12
|
+
obj = Item.new(itemhash)
|
13
|
+
@items << obj
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Instance methods
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
"Invoice ##{@id}"
|
21
|
+
end
|
22
|
+
|
23
|
+
# Class Methods
|
24
|
+
|
25
|
+
def self.list
|
26
|
+
result = TortoiseLabs::Client.get("/invoice/list")
|
27
|
+
invoices = Array.new
|
28
|
+
JSON.parse(result)["invoices"].each do |invoice|
|
29
|
+
obj = self.new(invoice)
|
30
|
+
invoices << obj
|
31
|
+
end
|
32
|
+
invoices
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.add_credit(amount)
|
36
|
+
response = TortoiseLabs::Client.post("/invoice/svccredit",
|
37
|
+
{:creditamt => amount})
|
38
|
+
return response.request.last_uri.to_s
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.get(id)
|
42
|
+
result = TortoiseLabs::Client.get("/invoice/#{id}")
|
43
|
+
self.new(JSON.parse(result)["invoice"])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Item
|
48
|
+
attr_reader :price, :btc_price, :description, :line_item, :invoice
|
49
|
+
attr_reader :entry_ts, :service
|
50
|
+
|
51
|
+
def initialize(ihash)
|
52
|
+
@btc_price, @price = ihash["btc_price"], ihash["price"]
|
53
|
+
@description, @line_item = ihash["description"], ihash["line_item"]
|
54
|
+
@entry_ts, @invoice = ihash["entry_ts"], ihash["invoice"]
|
55
|
+
@service = ihash["service"]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module TortoiseLabs
|
2
|
+
class Client
|
3
|
+
|
4
|
+
def self.base_uri
|
5
|
+
@base_uri ||= "https://manage.tortois.es"
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.base_uri=(value)
|
9
|
+
@base_uri = value.to_s.chomp("/")
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.username=(value)
|
13
|
+
@username = value
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.password=(value)
|
17
|
+
@password = value
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.auth_options
|
21
|
+
if @username.nil? or @password.nil?
|
22
|
+
raise NotAuthenticated
|
23
|
+
end
|
24
|
+
|
25
|
+
{:basic_auth => {:username => @username, :password => @password}}
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.get(path, options = {})
|
29
|
+
HTTParty.get(base_uri + path, options.merge(auth_options))
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.post(path, options)
|
33
|
+
options = {:body => options}.merge(auth_options)
|
34
|
+
HTTParty.post(base_uri + path, options)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module TortoiseLabs
|
2
|
+
|
3
|
+
module DNS
|
4
|
+
|
5
|
+
# DNS zone class
|
6
|
+
|
7
|
+
class Zone
|
8
|
+
attr_reader :id, :name, :records, :user
|
9
|
+
|
10
|
+
def initialize(zhash)
|
11
|
+
@id, @name, @user = zhash["id"], zhash["name"], zhash["user"]
|
12
|
+
@records = Array.new
|
13
|
+
|
14
|
+
zhash["records"].each do |record|
|
15
|
+
obj = Record.new(record)
|
16
|
+
obj.zoneid = @id
|
17
|
+
@records << obj
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Instance Methods
|
22
|
+
|
23
|
+
def delete
|
24
|
+
resp = TortoiseLabs::Client.get("/dns/zone/#{@id}/delete")
|
25
|
+
Zone.list
|
26
|
+
end
|
27
|
+
|
28
|
+
def new_record(subdomain, type, content, ttl = 3600, prio = 0)
|
29
|
+
resp = TortoiseLabs::Client.post("/dns/zone/#{@id}/record/new",
|
30
|
+
{:subdomain => subdomain, :type => type, :ttl => ttl,
|
31
|
+
:prio => prio, :content => content})
|
32
|
+
Zone.list[@name]
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
@name
|
37
|
+
end
|
38
|
+
|
39
|
+
# Class Methods
|
40
|
+
|
41
|
+
def self.list
|
42
|
+
response = TortoiseLabs::Client.get("/dns/zones").parsed_response
|
43
|
+
json = JSON.parse(response)
|
44
|
+
zones = Hash.new
|
45
|
+
|
46
|
+
json["zones"].each do |zone|
|
47
|
+
obj = self.new(zone)
|
48
|
+
zones[obj.name] = obj
|
49
|
+
end
|
50
|
+
|
51
|
+
zones
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.create(domain)
|
55
|
+
TortoiseLabs::Client.post("/dns/zone/new", {:domain_name => domain})
|
56
|
+
list = self.list
|
57
|
+
if list.keys.include?(domain)
|
58
|
+
return list[domain]
|
59
|
+
else
|
60
|
+
return false
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# DNS record class
|
66
|
+
|
67
|
+
class Record
|
68
|
+
attr_reader :id, :name, :content, :prio, :ttl, :type
|
69
|
+
attr_accessor :zoneid
|
70
|
+
|
71
|
+
def initialize(rhash)
|
72
|
+
@id, @name, @content = rhash["id"], rhash["name"], rhash["content"]
|
73
|
+
@prio, @ttl, @type = rhash["prio"], rhash["ttl"], rhash["type"]
|
74
|
+
end
|
75
|
+
|
76
|
+
def modify(new_content, subdomain = @name)
|
77
|
+
TortoiseLabs::Client.post("/dns/zone/#{@zoneid}/record/#{@id}",
|
78
|
+
{:content => new_content, :subdomain => subdomain})
|
79
|
+
Zone.list.values.select { |z| z.id == zoneid }[0]
|
80
|
+
end
|
81
|
+
|
82
|
+
def delete
|
83
|
+
resp = TortoiseLabs::Client.get("/dns/zone/#{@zoneid}/record/#{@id}/delete")
|
84
|
+
Zone.new(JSON.parse(resp)["zone"])
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_s
|
88
|
+
"#{@type}:#{@name}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
@@ -0,0 +1,230 @@
|
|
1
|
+
module TortoiseLabs
|
2
|
+
|
3
|
+
# IPs
|
4
|
+
|
5
|
+
class IP
|
6
|
+
attr_reader :broadcast, :netmask, :version, :gateway, :network, :ip
|
7
|
+
|
8
|
+
def initialize(iphash)
|
9
|
+
@ip = iphash["ip"]
|
10
|
+
ipnet = iphash["ipnet"]
|
11
|
+
@netmask, @broadcast, @version, @gateway, @network = ipnet["netmask"],
|
12
|
+
ipnet["broadcast"], ipnet["version"].to_i, ipnet["gateway"],
|
13
|
+
ipnet["network"]
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
@ip
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Jobs
|
22
|
+
|
23
|
+
class Job
|
24
|
+
attr_reader :id, :method, :entry_ts, :start_ts, :success
|
25
|
+
|
26
|
+
def initialize(job)
|
27
|
+
@id, @method, @entry_ts, @start_ts = job["id"], job["req_env"]["method"],
|
28
|
+
job["entry_ts"], job["start_ts"]
|
29
|
+
|
30
|
+
@success = job["rsp_env"]["params"]["success"]
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
"Job #{@id}: #{@method}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def success?
|
38
|
+
@success
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# VPS
|
43
|
+
|
44
|
+
class VPS
|
45
|
+
attr_reader :id, :disk, :mac, :memory, :name, :node
|
46
|
+
attr_reader :swap, :user, :nickname, :ips
|
47
|
+
|
48
|
+
# Instance methods
|
49
|
+
|
50
|
+
def initialize(vps)
|
51
|
+
@node, @name, @mac, @memory, @disk = vps["node"], vps["name"],
|
52
|
+
vps["mac"], vps["memory"], vps["disk"]
|
53
|
+
|
54
|
+
@nickname, @id, @swap, @user = vps["nickname"], vps["id"],
|
55
|
+
vps["swap"], vps["user"]
|
56
|
+
|
57
|
+
@ips = Hash.new
|
58
|
+
vps["ips"].each do |iphash|
|
59
|
+
obj = IP.new(iphash)
|
60
|
+
@ips[obj.ip] = obj
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def to_s
|
65
|
+
@nickname
|
66
|
+
end
|
67
|
+
|
68
|
+
def nickname=(newnickname)
|
69
|
+
options = {:nickname => newnickname}
|
70
|
+
result = TortoiseLabs::Client.post("/vps/#{@id}/setnickname", options)
|
71
|
+
@nickname = result["nickname"]
|
72
|
+
end
|
73
|
+
|
74
|
+
def monitoring=(boolean)
|
75
|
+
if boolean
|
76
|
+
result = TortoiseLabs::Client.get("/vps/#{@id}/monitoring/enable")
|
77
|
+
else
|
78
|
+
result = TortoiseLabs::Client.get("/vps/#{@id}/monitoring/disable")
|
79
|
+
end
|
80
|
+
boolean
|
81
|
+
end
|
82
|
+
|
83
|
+
def monitoring?
|
84
|
+
vps = JSON.parse(TortoiseLabs::Client.get("/vps/#{id}"))
|
85
|
+
vps["service"]["monitoring"]
|
86
|
+
end
|
87
|
+
|
88
|
+
def templates
|
89
|
+
result = TortoiseLabs::Client.get("/vps/#{@id}/deploy")
|
90
|
+
JSON.parse(result)["templates"]
|
91
|
+
end
|
92
|
+
|
93
|
+
def deploy(image, rootpass, arch = "x86_64")
|
94
|
+
# arch can be either x86_64 or i386
|
95
|
+
# Image is one of the values returned by the templates method above
|
96
|
+
|
97
|
+
unless image =~ /_login\.xml$/i
|
98
|
+
image = image + "_login.xml"
|
99
|
+
end
|
100
|
+
|
101
|
+
result = TortoiseLabs::Client.post("/vps/#{@id}/deploy",
|
102
|
+
{:imagename => image, :rootpass => rootpass, :arch => arch})
|
103
|
+
jobs
|
104
|
+
end
|
105
|
+
|
106
|
+
def running?
|
107
|
+
result = TortoiseLabs::Client.get("/vps/#{@id}/status.json")
|
108
|
+
result.parsed_response["running"]
|
109
|
+
end
|
110
|
+
|
111
|
+
def destroy
|
112
|
+
result = TortoiseLabs::Client.get("/vps/#{@id}/destroy")
|
113
|
+
result.parsed_response["job"]
|
114
|
+
end
|
115
|
+
|
116
|
+
def shutdown
|
117
|
+
result = TortoiseLabs::Client.get("/vps/#{@id}/shutdown")
|
118
|
+
result.parsed_response["job"]
|
119
|
+
end
|
120
|
+
|
121
|
+
def create
|
122
|
+
result = TortoiseLabs::Client.get("/vps/#{@id}/create")
|
123
|
+
result.parsed_response["job"]
|
124
|
+
end
|
125
|
+
|
126
|
+
def powercycle
|
127
|
+
result = TortoiseLabs::Client.get("/vps/#{@id}/powercycle")
|
128
|
+
result.parsed_response["job"]
|
129
|
+
end
|
130
|
+
|
131
|
+
def jobs
|
132
|
+
res = TortoiseLabs::Client.get("/vps/#{@id}/jobs.json").parsed_response
|
133
|
+
|
134
|
+
jobs = Hash.new
|
135
|
+
res.each do |jobhash|
|
136
|
+
begin
|
137
|
+
obj = Job.new(jobhash)
|
138
|
+
jobs[obj.id] = obj
|
139
|
+
rescue NoMethodError => err
|
140
|
+
# occurs when there are no jobs
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
jobs
|
145
|
+
end
|
146
|
+
|
147
|
+
def hvm
|
148
|
+
result = TortoiseLabs::Client.get("/vps/#{@id}/hvm").parsed_response
|
149
|
+
JSON.parse(result)["isolist"]
|
150
|
+
end
|
151
|
+
|
152
|
+
def set_iso(isoid)
|
153
|
+
result = TortoiseLabs::Client.post("/vps/#{@id}/hvm/setiso",
|
154
|
+
{:isoid => isoid})
|
155
|
+
hvm
|
156
|
+
end
|
157
|
+
|
158
|
+
def set_boot_order(bootorder)
|
159
|
+
result = TortoiseLabs::Client.post("/vps/#{@id}/hvm/setbootorder",
|
160
|
+
{:bootorder => bootorder})
|
161
|
+
result.parsed_response["isolist"]
|
162
|
+
end
|
163
|
+
|
164
|
+
def set_nic_type(nictype)
|
165
|
+
# nictype can be e1000, virtio-net or rtl8139
|
166
|
+
result = TortoiseLabs::Client.post("/vps/#{@id}/hvm/setnictype",
|
167
|
+
{:nictype => nictype})
|
168
|
+
hvm
|
169
|
+
end
|
170
|
+
|
171
|
+
def new_iso(isoname, isouri)
|
172
|
+
result = TortoiseLabs::Client.post("/vps/#{@id}/hvmiso/new",
|
173
|
+
{:isoname => isoname, :isouri => isouri})
|
174
|
+
hvm
|
175
|
+
end
|
176
|
+
|
177
|
+
def delete_iso(isoid)
|
178
|
+
result = TortoiseLabs::Client.post("/vps/#{@id}/hvmiso/#{isoid}/delete")
|
179
|
+
hvm
|
180
|
+
end
|
181
|
+
|
182
|
+
# Class methods
|
183
|
+
|
184
|
+
def self.list
|
185
|
+
json = JSON.parse(TortoiseLabs::Client.get("/vps/list"))
|
186
|
+
return nil if json.empty?
|
187
|
+
|
188
|
+
vpses = Hash.new
|
189
|
+
json["vpslist"].each do |vps|
|
190
|
+
obj = self.new(vps)
|
191
|
+
vpses[obj.nickname] = obj
|
192
|
+
end
|
193
|
+
|
194
|
+
vpses
|
195
|
+
end
|
196
|
+
|
197
|
+
# This is commented out because the API method itself is broken
|
198
|
+
# and I cannot verify it works. I will uncomment it when I can.
|
199
|
+
# def self.regions
|
200
|
+
# result = JSON.parse(TortoiseLabs::Client.get("/vps/signup"))["regions"]
|
201
|
+
# regions = Array.new
|
202
|
+
# result.each { |r| regions << Region.new(r["id"], r["name"]) }
|
203
|
+
# regions
|
204
|
+
# end
|
205
|
+
|
206
|
+
# def self.plans
|
207
|
+
# result = JSON.parse(TortoiseLabs::Client.get("/vps/signup"))
|
208
|
+
# plans = Array.new
|
209
|
+
# result["resource_plans"].each do |p|
|
210
|
+
# obj = Plan.new(p["id"], p["disk"], p["memory"], p["name"],
|
211
|
+
# p["price_btc"], p["price_usd"], p["swap"])
|
212
|
+
# plans << obj
|
213
|
+
# end
|
214
|
+
# plans
|
215
|
+
# end
|
216
|
+
|
217
|
+
def self.get(id)
|
218
|
+
vpshash = JSON.parse(TortoiseLabs::Client.get("/vps/#{id}"))["service"]
|
219
|
+
self.new(vpshash)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# Helper structs
|
224
|
+
|
225
|
+
Region = Struct.new(:id, name)
|
226
|
+
|
227
|
+
Plan = Struct.new(:id, :disk, :memory, :name, :price_btc,
|
228
|
+
:price_usd, :swap)
|
229
|
+
|
230
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tortoiselabs
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Northall
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-10-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: httparty
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: A TortoiseLabs API wrapper.
|
28
|
+
email: andrew@northall.me.uk
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- lib/tortoiselabs.rb
|
34
|
+
- lib/tortoiselabs/billing.rb
|
35
|
+
- lib/tortoiselabs/client.rb
|
36
|
+
- lib/tortoiselabs/dns.rb
|
37
|
+
- lib/tortoiselabs/vps.rb
|
38
|
+
homepage: https://github.com/somasonic/tortoiselabs-ruby
|
39
|
+
licenses:
|
40
|
+
- MIT
|
41
|
+
metadata: {}
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 2.0.0
|
59
|
+
signing_key:
|
60
|
+
specification_version: 4
|
61
|
+
summary: A TortoiseLabs API wrapper
|
62
|
+
test_files: []
|