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 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
@@ -0,0 +1,7 @@
1
+ require 'httparty'
2
+ require 'json'
3
+
4
+ require 'tortoiselabs/client'
5
+ require 'tortoiselabs/vps'
6
+ require 'tortoiselabs/dns'
7
+ require 'tortoiselabs/billing'
@@ -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: []