snuggie 0.1.0
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.
- data/README.markdown +98 -0
- data/Rakefile +31 -0
- data/lib/snuggie.rb +17 -0
- data/lib/snuggie/config.rb +10 -0
- data/lib/snuggie/errors.rb +6 -0
- data/lib/snuggie/noc.rb +276 -0
- data/lib/snuggie/version.rb +3 -0
- data/test/fixtures/buy_license.txt +1 -0
- data/test/fixtures/cancel_license.txt +1 -0
- data/test/fixtures/edit_ips.txt +1 -0
- data/test/fixtures/invoice_details_unbilled.txt +1 -0
- data/test/fixtures/license_logs.txt +1 -0
- data/test/fixtures/list_licenses.txt +1 -0
- data/test/fixtures/refund.txt +1 -0
- data/test/snuggie/config_test.rb +15 -0
- data/test/snuggie/noc_test.rb +279 -0
- data/test/snuggie_test.rb +31 -0
- data/test/test_helper.rb +138 -0
- metadata +105 -0
data/README.markdown
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
# Snuggie [][Build Status]
|
2
|
+
|
3
|
+
Snuggie wraps the Softaculous API in a warm, loving ruby embrace.
|
4
|
+
|
5
|
+
Snuggie has been tested on on MRI 1.8.4, MRI 1.8.7, MRI 1.9.2,
|
6
|
+
Rubinius 2.0.0pre, and JRuby 1.6.2.
|
7
|
+
|
8
|
+
[Build Status]: http://travis-ci.org/site5/snuggie
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
gem install snuggie
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
Create a new `Snuggie::NOC` object with your credentials:
|
17
|
+
|
18
|
+
noc = Snuggie::NOC.new(
|
19
|
+
:username => 'marty',
|
20
|
+
:password => 'mcSUPERfly'
|
21
|
+
)
|
22
|
+
|
23
|
+
Your Softaculous credentials can also be configured globally:
|
24
|
+
|
25
|
+
Snuggie.configure do |config|
|
26
|
+
config.username = 'marty'
|
27
|
+
config.password = 'mcSUPERfly'
|
28
|
+
end
|
29
|
+
|
30
|
+
noc = Snuggie::NOC.new
|
31
|
+
|
32
|
+
Buy/renew a license
|
33
|
+
|
34
|
+
noc.buy_license(
|
35
|
+
:ip => '127.0.0.1',
|
36
|
+
:months_to_add => 1,
|
37
|
+
:server_type => :dedicated,
|
38
|
+
:auth_email => 'marty@hilldale.edu',
|
39
|
+
:auto_renew => true
|
40
|
+
)
|
41
|
+
|
42
|
+
Refund a transaction
|
43
|
+
|
44
|
+
noc.refund :action_id => 99999
|
45
|
+
|
46
|
+
List all licenses
|
47
|
+
|
48
|
+
noc.list_licenses
|
49
|
+
|
50
|
+
List licenses by IP
|
51
|
+
|
52
|
+
noc.list_licenses :ip => '127.0.0.1'
|
53
|
+
|
54
|
+
List all expired licenses
|
55
|
+
|
56
|
+
noc.list_licenses :expired => 1
|
57
|
+
|
58
|
+
List licenses expiring in 7 days
|
59
|
+
|
60
|
+
noc.list_licenses :expired => 2
|
61
|
+
|
62
|
+
List licenses expiring in 15 days
|
63
|
+
|
64
|
+
noc.list_licenses :expired => 3
|
65
|
+
|
66
|
+
Get invoice details
|
67
|
+
|
68
|
+
noc.invoice_details :invoice_id => 99999
|
69
|
+
|
70
|
+
Get unbilled transactions for the current month:
|
71
|
+
|
72
|
+
noc.invoice_details
|
73
|
+
|
74
|
+
Cancel a license by key
|
75
|
+
|
76
|
+
noc.cancel_license :key => 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX'
|
77
|
+
|
78
|
+
Cancel a license by IP
|
79
|
+
|
80
|
+
noc.cancel_license :ip => '127.0.0.1'
|
81
|
+
|
82
|
+
Get Action/Activity logs for a license
|
83
|
+
|
84
|
+
noc.license_logs :key => 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX'
|
85
|
+
|
86
|
+
## Note on Patches/Pull Requests
|
87
|
+
|
88
|
+
* Fork the project.
|
89
|
+
* Make your feature addition or bug fix.
|
90
|
+
* Add tests for it. This is important so I don't break it in a future version
|
91
|
+
unintentionally.
|
92
|
+
* Commit, do not bump version. (If you want to have your own version, that is
|
93
|
+
fine but bump version in a commit by itself I can ignore when I pull.)
|
94
|
+
* Send me a pull request. Bonus points for topic branches.
|
95
|
+
|
96
|
+
## Copyright
|
97
|
+
|
98
|
+
Copyright (c) 2011 Site5 LLC. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
$:.unshift 'lib'
|
2
|
+
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
Rake::TestTask.new do |test|
|
6
|
+
test.libs << "test"
|
7
|
+
test.test_files = FileList['test/**/*_test.rb']
|
8
|
+
end
|
9
|
+
|
10
|
+
task :default => :test
|
11
|
+
|
12
|
+
desc "Open an irb session preloaded with this library"
|
13
|
+
task :console do
|
14
|
+
sh "irb -rubygems -r ./lib/snuggie.rb -I ./lib"
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Push a new version to rubygems.org"
|
18
|
+
task :publish do
|
19
|
+
require 'snuggie/version'
|
20
|
+
|
21
|
+
ver = Snuggie::Version
|
22
|
+
|
23
|
+
mkdir("pkg") unless File.exists?("pkg")
|
24
|
+
|
25
|
+
sh "gem build snuggie.gemspec"
|
26
|
+
sh "gem push snuggie-#{ver}.gem"
|
27
|
+
sh "git tag -a -m 'Snuggie v#{ver}' v#{ver}"
|
28
|
+
sh "git push origin v#{ver}"
|
29
|
+
sh "git push origin master"
|
30
|
+
sh "mv snuggie-#{ver}.gem pkg"
|
31
|
+
end
|
data/lib/snuggie.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Snuggie
|
2
|
+
autoload :Version, "snuggie/version"
|
3
|
+
autoload :Errors, "snuggie/errors"
|
4
|
+
autoload :Config, "snuggie/config"
|
5
|
+
autoload :NOC, "snuggie/noc"
|
6
|
+
|
7
|
+
class << self
|
8
|
+
attr_accessor :config
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.configure
|
12
|
+
yield config if block_given?
|
13
|
+
config
|
14
|
+
end
|
15
|
+
|
16
|
+
self.config = Config.new
|
17
|
+
end
|
data/lib/snuggie/noc.rb
ADDED
@@ -0,0 +1,276 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'net/http'
|
3
|
+
require 'php_serialize'
|
4
|
+
|
5
|
+
module Snuggie
|
6
|
+
# Snuggie::NOC is the main class for communicating with the
|
7
|
+
# Softaculous NOC API.
|
8
|
+
class NOC
|
9
|
+
|
10
|
+
# The Softaculous NOC API lives here
|
11
|
+
API_URL = 'http://www.softaculous.com/noc'
|
12
|
+
|
13
|
+
# Creates a new Snuggie::NOC instance
|
14
|
+
#
|
15
|
+
# Params
|
16
|
+
#
|
17
|
+
# * credentials - (Optional) a hash with :username, :password to
|
18
|
+
# be used to authenticate with Softaculous. If not
|
19
|
+
# provided, the Snuggie will try using those
|
20
|
+
# configured via `Snuggie#configure`
|
21
|
+
def initialize(credentials = {})
|
22
|
+
credentials = {
|
23
|
+
:username => Snuggie.config.username,
|
24
|
+
:password => Snuggie.config.password
|
25
|
+
} if credentials.empty? && Snuggie.config.username && Snuggie.config.password
|
26
|
+
|
27
|
+
@credentials = credentials
|
28
|
+
end
|
29
|
+
|
30
|
+
# Buy a license
|
31
|
+
#
|
32
|
+
# NOTE: You must specify either months_to_add or years_to_add
|
33
|
+
#
|
34
|
+
# Params
|
35
|
+
#
|
36
|
+
# * ip - The IP of the license to be Purchased or Renewed
|
37
|
+
# * months_to_add - Months to buy/renew the license for
|
38
|
+
# * years_to_add - Years to buy/renew the license for
|
39
|
+
# * server_type - Type of server used by this license, should be
|
40
|
+
# :dedicated or :vps
|
41
|
+
# * auth_email - When buying a new license, this is required to
|
42
|
+
# verify the owner of the License. This address will
|
43
|
+
# be used to send reminders when the license is
|
44
|
+
# expiring. Not required for renewals
|
45
|
+
# * auto_renew - Renew this license automatically before
|
46
|
+
# expiration. Set to true or false.
|
47
|
+
def buy_license(params = {})
|
48
|
+
params[:ips] = params.delete(:ip) if params[:ip]
|
49
|
+
params[:autorenew] = params.delete(:auto_renew) if params[:auto_renew]
|
50
|
+
params[:authemail] = params.delete(:auth_email) if params[:auth_email]
|
51
|
+
params[:servertype] = params.delete(:server_type) if params[:server_type]
|
52
|
+
|
53
|
+
if params[:months_to_add]
|
54
|
+
params[:toadd] = "#{params.delete(:months_to_add)}M"
|
55
|
+
elsif params[:years_to_add]
|
56
|
+
params[:toadd] = "#{params.delete(:years_to_add)}Y"
|
57
|
+
end
|
58
|
+
|
59
|
+
if [:dedicated, :vps].include?(params[:servertype])
|
60
|
+
params[:servertype] = params[:servertype] == :dedicated ? 1 : 2
|
61
|
+
end
|
62
|
+
|
63
|
+
if params.has_key?(:autorenew)
|
64
|
+
params[:autorenew] = params[:autorenew] === true ? 1 : 2
|
65
|
+
end
|
66
|
+
|
67
|
+
commit(params.merge!(:ca => :buy, :purchase => 1),
|
68
|
+
:require => [:purchase, :ips, :toadd, :servertype, :autorenew]
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Refund a transaction
|
73
|
+
#
|
74
|
+
# NOTE: A refund can only be issued within 7 days of buying/renewing
|
75
|
+
# a license.
|
76
|
+
#
|
77
|
+
# Params
|
78
|
+
#
|
79
|
+
# * action_id - The Action ID to clain a refund for
|
80
|
+
def refund(params = {})
|
81
|
+
params[:actid] = params.delete(:action_id) if params[:action_id]
|
82
|
+
params[:ca] = :refund
|
83
|
+
commit(params, :require => [:actid])
|
84
|
+
end
|
85
|
+
|
86
|
+
# List licenses
|
87
|
+
#
|
88
|
+
# NOTE: All parameters are optional. If called without parameters, a
|
89
|
+
# list of all of your licenses will be returned.
|
90
|
+
#
|
91
|
+
# Params
|
92
|
+
#
|
93
|
+
# * key - (Optional) Search for a specific License by License Key
|
94
|
+
# * ip - (Optional) Search for a specific License by Primary IP
|
95
|
+
# * expiry - (Optional) Fetch a list of Licenses that are expiring
|
96
|
+
# Set to 1 to list all expired licenses on your account
|
97
|
+
# Set to 2 to list licenses expiring in the next 7 days
|
98
|
+
# Set to 3 to list licenses expiring in the next 15 days
|
99
|
+
# * start - (Optional) The starting point to return from
|
100
|
+
# Eg: specify 99 if you have 500 licenses and want to
|
101
|
+
# return licenses 100-500.
|
102
|
+
# * limit - (Optional) The length to limit the result set to
|
103
|
+
# Eg: specify 100 if you have 500 licenses and want to
|
104
|
+
# limit the result set to 100 items
|
105
|
+
def list_licenses(params = {})
|
106
|
+
params[:len] = params.delete(:limit) if params[:limit]
|
107
|
+
params[:ca] = :licenses
|
108
|
+
commit(params)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Cancel license
|
112
|
+
#
|
113
|
+
# NOTES:
|
114
|
+
# * Either ip or key needs to be specified
|
115
|
+
# * Cancellations are not allowed on licenses expiring more than 1
|
116
|
+
# month in the future.
|
117
|
+
# * A refund is **NOT** applied when you cancel a license. You must
|
118
|
+
# claim the refund using Snuggie::NOC#refund
|
119
|
+
#
|
120
|
+
# Params
|
121
|
+
#
|
122
|
+
# * key - (Optional) The license key
|
123
|
+
# * ip - (Optional) The Primary IP of the license
|
124
|
+
def cancel_license(params = {})
|
125
|
+
params[:lickey] = params.delete(:key) if params[:key]
|
126
|
+
params[:licip] = params.delete(:ip) if params[:ip]
|
127
|
+
commit(params.merge!(:ca => :cancel, :cancel_license => 1),
|
128
|
+
:require_one => [:lickey, :licip]
|
129
|
+
)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Edit IPs associated with a license
|
133
|
+
#
|
134
|
+
# Params
|
135
|
+
#
|
136
|
+
# * license_id - The license ID (**NOT** the license key)
|
137
|
+
# * ips - The list of IPs of the same VPS/Server. The first IP is
|
138
|
+
# the Primary IP. You may add up to 8 IPs
|
139
|
+
def edit_ips(params = {})
|
140
|
+
params[:'ips[]'] = params.delete(:ips)
|
141
|
+
params[:lid] = params.delete(:license_id) if params[:license_id]
|
142
|
+
commit(params.merge!(:ca => :showlicense, :editlicense => 1),
|
143
|
+
:require => [:lid, :'ips[]']
|
144
|
+
)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Get details for an invoice
|
148
|
+
#
|
149
|
+
# NOTE: If invoid is 0 or not set, a list of **all** unbilled
|
150
|
+
# transactions for the current month will be returned
|
151
|
+
#
|
152
|
+
# Params
|
153
|
+
#
|
154
|
+
# * invoice_id - The invoice ID to getch details for.
|
155
|
+
def invoice_details(params = {})
|
156
|
+
params[:invoid] = params.delete(:invoice_id) if params[:invoice_id]
|
157
|
+
params[:ca] = :invoicedetails
|
158
|
+
commit(params)
|
159
|
+
end
|
160
|
+
|
161
|
+
# Get Action Logs for a license
|
162
|
+
#
|
163
|
+
# NOTE: The logs are returned in **DESCENDING ORDER**, meaning the
|
164
|
+
# latest logs will appear first.
|
165
|
+
#
|
166
|
+
# Params
|
167
|
+
#
|
168
|
+
# * key - The license key
|
169
|
+
# * limit - The number of action logs to return
|
170
|
+
def license_logs(params = {})
|
171
|
+
params[:ca] = :licenselogs
|
172
|
+
commit(params, :require => :key)
|
173
|
+
end
|
174
|
+
|
175
|
+
private
|
176
|
+
|
177
|
+
# Send a request upstream to Softaculous
|
178
|
+
#
|
179
|
+
# Params
|
180
|
+
#
|
181
|
+
# * params - a hash of parameters for the request
|
182
|
+
# * options - a hash of options, used to validate required params
|
183
|
+
def commit(params, options = {})
|
184
|
+
if options[:require]
|
185
|
+
unless require_params(params, options[:require])
|
186
|
+
raise Errors::MissingArgument
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
if options[:require_one]
|
191
|
+
unless require_one_of(params, options[:require_one])
|
192
|
+
raise Errors::MissingArgument
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
params.merge!(@credentials) unless @credentials.nil? || @credentials.empty?
|
197
|
+
|
198
|
+
uri = "#{API_URL}?#{query_string(params)}"
|
199
|
+
if res = fetch(uri)
|
200
|
+
@response = begin
|
201
|
+
PHP.unserialize(res.body)
|
202
|
+
rescue
|
203
|
+
res.body
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# Returns true if params has all of the specified keys
|
209
|
+
#
|
210
|
+
# Params
|
211
|
+
#
|
212
|
+
# * params - hash of query parameters
|
213
|
+
# * keys - keys to search for in params
|
214
|
+
def require_params(params, keys)
|
215
|
+
Array(keys).each { |key| return false unless params[key] }
|
216
|
+
true
|
217
|
+
end
|
218
|
+
|
219
|
+
# Returns true if params has one of the specified keys
|
220
|
+
#
|
221
|
+
# Params
|
222
|
+
#
|
223
|
+
# * params - hash of query parameters
|
224
|
+
# * keys - keys to search for in params
|
225
|
+
def require_one_of(params, keys)
|
226
|
+
Array(keys).each { |key| return true if params[key] }
|
227
|
+
false
|
228
|
+
end
|
229
|
+
|
230
|
+
# Formats params into a query string for a GET request
|
231
|
+
#
|
232
|
+
# NOTE: For convenience, this converts the keys :username and
|
233
|
+
# :password to :nocname and :nocpass respectively.
|
234
|
+
#
|
235
|
+
# Params
|
236
|
+
#
|
237
|
+
# * params - hash of query parameters
|
238
|
+
def query_string(params)
|
239
|
+
params.map do |key, val|
|
240
|
+
case key.to_sym
|
241
|
+
when :username
|
242
|
+
key = :nocname
|
243
|
+
when :password
|
244
|
+
key = :nocpass
|
245
|
+
end
|
246
|
+
"#{key}=#{CGI.escape(val.to_s)}"
|
247
|
+
end.join('&')
|
248
|
+
end
|
249
|
+
|
250
|
+
# Performs a GET request on the given URI, redirects if needed
|
251
|
+
#
|
252
|
+
# See Following Redirection at
|
253
|
+
# http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/classes/Net/HTTP.html
|
254
|
+
#
|
255
|
+
# Params
|
256
|
+
#
|
257
|
+
# * uri_str - the URL to fetch as a string
|
258
|
+
# * limit - number of redirects to allow
|
259
|
+
def fetch(uri_str, limit = 10)
|
260
|
+
# You should choose better exception.
|
261
|
+
raise ArgumentError, 'HTTP redirect too deep' if limit == 0
|
262
|
+
|
263
|
+
uri = URI.parse(uri_str)
|
264
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
265
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
266
|
+
response = http.start { |http| http.request(request) }
|
267
|
+
|
268
|
+
case response
|
269
|
+
when Net::HTTPSuccess then response
|
270
|
+
when Net::HTTPRedirection then fetch(response['location'], limit - 1)
|
271
|
+
else
|
272
|
+
response.error!
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
a:12:{s:3:"lid";i:99999;s:7:"license";s:29:"XXXXX-XXXXX-XXXXX-XXXXX-XXXXX";s:3:"bal";d:-48;s:2:"ip";s:9:"127.0.0.1";s:4:"time";i:1308062889;s:4:"rate";i:2;s:3:"amt";i:2;s:5:"added";s:2:"1M";s:6:"action";s:3:"new";s:9:"autorenew";s:3:"YES";s:5:"actid";i:99999;s:5:"error";N;}
|
@@ -0,0 +1 @@
|
|
1
|
+
a:2:{s:5:"error";N;s:17:"cancelled_license";a:15:{s:6:"apiuid";s:1:"0";s:5:"nocid";s:4:"XXXX";s:10:"servertype";s:1:"1";s:7:"license";s:29:"XXXXX-XXXXX-XXXXX-XXXXX-XXXXX";s:4:"time";s:10:"1308062889";s:7:"expires";s:8:"20110614";s:3:"env";s:0:"";s:4:"type";s:1:"1";s:9:"last_sync";s:1:"0";s:3:"lid";s:5:"99999";s:10:"soft_email";s:0:"";s:5:"panel";s:0:"";s:9:"authemail";s:18:"marty@hilldale.edu";s:6:"unique";s:0:"";s:6:"active";s:1:"1";}}
|
@@ -0,0 +1 @@
|
|
1
|
+
a:3:{s:5:"error";N;s:7:"new_ips";a:1:{i:0;s:9:"127.0.0.2";}s:3:"lid";i:99999;}
|
@@ -0,0 +1 @@
|
|
1
|
+
a:3:{s:7:"actions";a:2:{i:XXXXX;a:12:{s:5:"actid";s:5:"XXXXX";s:5:"nocid";s:4:"XXXX";s:6:"action";s:7:"advance";s:3:"lid";s:1:"0";s:6:"invoid";s:1:"0";s:4:"rate";s:5:"50.00";s:5:"added";s:0:"";s:3:"amt";s:6:"-50.00";s:4:"time";s:10:"1307554880";s:4:"date";s:8:"20110608";s:8:"refunded";s:1:"0";s:7:"license";N;}i:XXXXX;a:12:{s:5:"actid";s:5:"XXXXX";s:5:"nocid";s:4:"XXXX";s:6:"action";s:3:"new";s:3:"lid";s:5:"XXXXX";s:6:"invoid";s:1:"0";s:4:"rate";s:4:"2.00";s:5:"added";s:2:"1M";s:3:"amt";s:4:"2.00";s:4:"time";s:10:"1308062889";s:4:"date";s:8:"20110614";s:8:"refunded";s:1:"0";s:7:"license";s:29:"XXXXX-XXXXX-XXXXX-XXXXX-XXXXX";}}s:3:"amt";d:-48;s:6:"invoid";i:0;}
|
@@ -0,0 +1 @@
|
|
1
|
+
a:3:{s:7:"actions";a:1:{i:XXXXX;a:11:{s:5:"actid";s:5:"XXXXX";s:5:"nocid";s:4:"XXXX";s:6:"action";s:3:"new";s:3:"lid";s:5:"XXXXX";s:6:"invoid";s:1:"0";s:4:"rate";s:4:"2.00";s:5:"added";s:2:"1M";s:3:"amt";s:4:"2.00";s:4:"time";s:10:"1308062889";s:4:"date";s:8:"20110614";s:8:"refunded";s:1:"0";}}s:7:"license";a:15:{s:3:"lid";s:5:"XXXXX";s:7:"license";s:29:"XXXXX-XXXXX-XXXXX-XXXXX-XXXXX";s:4:"type";s:1:"1";s:6:"unique";s:0:"";s:6:"apiuid";s:1:"0";s:5:"nocid";s:4:"XXXX";s:9:"authemail";s:18:"marty@hilldale.edu";s:10:"soft_email";s:0:"";s:4:"time";s:10:"1308062889";s:7:"expires";s:8:"20110714";s:6:"active";s:1:"1";s:10:"servertype";s:1:"1";s:9:"last_sync";s:1:"0";s:5:"panel";s:0:"";s:3:"env";s:0:"";}s:5:"error";N;}
|
@@ -0,0 +1 @@
|
|
1
|
+
a:4:{s:8:"licenses";a:1:{i:99999;a:19:{s:3:"lid";s:5:"XXXXX";s:7:"license";s:29:"XXXXX-XXXXX-XXXXX-XXXXX-XXXXX";s:4:"type";s:1:"1";s:6:"unique";s:0:"";s:6:"apiuid";s:1:"0";s:5:"nocid";s:4:"XXXX";s:9:"authemail";s:18:"marty@hilldale.org";s:10:"soft_email";s:0:"";s:4:"time";s:10:"1308062889";s:7:"expires";s:8:"20110614";s:6:"active";s:1:"1";s:10:"servertype";s:1:"1";s:9:"last_sync";s:1:"0";s:5:"panel";s:0:"";s:3:"env";s:0:"";s:4:"ipid";s:5:"XXXXX";s:2:"ip";s:9:"127.0.0.1";s:7:"primary";s:1:"1";s:8:"hostname";s:12:"hilldale.org";}}s:10:"num_active";i:1;s:11:"num_results";i:1;s:5:"error";N;}
|
@@ -0,0 +1 @@
|
|
1
|
+
a:10:{s:3:"lid";s:5:"XXXXX";s:7:"license";s:29:"XXXXX-XXXXX-XXXXX-XXXXX-XXXXX";s:3:"bal";d:-50;s:4:"time";i:1308066592;s:4:"rate";s:4:"2.00";s:3:"amt";d:-2;s:5:"added";s:3:"-1M";s:6:"action";s:6:"refund";s:5:"actid";i:99999;s:5:"error";N;}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
context "Snuggie::Config" do
|
4
|
+
setup do
|
5
|
+
@config = Snuggie::Config.new
|
6
|
+
end
|
7
|
+
|
8
|
+
test "has attr_accessor :username" do
|
9
|
+
assert_attr_accessor @config, :username
|
10
|
+
end
|
11
|
+
|
12
|
+
test "has attr_accessor :password" do
|
13
|
+
assert_attr_accessor @config, :password
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,279 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
context "Snuggie::NOC" do
|
4
|
+
TEST_CREDENTIALS = { :username => 'marty', :password => 'mcSUPERfly' }
|
5
|
+
|
6
|
+
setup do
|
7
|
+
@noc = Snuggie::NOC.new(TEST_CREDENTIALS)
|
8
|
+
end
|
9
|
+
|
10
|
+
def mock_query_url(params = {})
|
11
|
+
@noc.class::API_URL + '?' + @noc.instance_eval { query_string(params) }
|
12
|
+
end
|
13
|
+
|
14
|
+
test "::API_URL has a valid format" do
|
15
|
+
assert_valid_url @noc.class::API_URL
|
16
|
+
end
|
17
|
+
|
18
|
+
test "#initialize sets @credentials" do
|
19
|
+
credentials = @noc.instance_variable_get(:@credentials)
|
20
|
+
assert credentials.is_a?(Hash)
|
21
|
+
TEST_CREDENTIALS.each do |key, val|
|
22
|
+
assert credentials.has_key?(key)
|
23
|
+
assert_equal val, credentials[key]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
test "#initialize uses Config to set @credentials" do
|
28
|
+
Snuggie.configure do |c|
|
29
|
+
c.username = 'doc'
|
30
|
+
c.password = 'clara'
|
31
|
+
end
|
32
|
+
credentials = @noc.class.new.instance_variable_get(:@credentials)
|
33
|
+
assert credentials.is_a?(Hash)
|
34
|
+
({ :username => 'doc', :password => 'clara' }).each do |key, val|
|
35
|
+
assert_not_nil credentials[key]
|
36
|
+
assert credentials.has_key?(key)
|
37
|
+
end
|
38
|
+
|
39
|
+
Snuggie.configure do |c|
|
40
|
+
c.username = nil
|
41
|
+
c.password = nil
|
42
|
+
end
|
43
|
+
assert_equal @noc.class.new.instance_variable_get(:@credentials), Hash.new
|
44
|
+
end
|
45
|
+
|
46
|
+
test "#require_params returns true if all params are set" do
|
47
|
+
a1 = @noc.instance_eval do
|
48
|
+
require_params({ :fuel => :plutonium, :date => 1955 }, [:fuel, :date])
|
49
|
+
end
|
50
|
+
assert a1
|
51
|
+
end
|
52
|
+
|
53
|
+
test "#require_one_of returns true if one param is set" do
|
54
|
+
a1 = @noc.instance_eval do
|
55
|
+
require_one_of({ :date => 1955, :fuel => :plutonium }, [:fusion, :fuel])
|
56
|
+
end
|
57
|
+
assert a1
|
58
|
+
end
|
59
|
+
|
60
|
+
test "#query_string" do
|
61
|
+
params = {
|
62
|
+
:date => 1955,
|
63
|
+
:fuel => :plutonium,
|
64
|
+
:username => 'marty',
|
65
|
+
:password => 'mcSUPERfly'
|
66
|
+
}
|
67
|
+
|
68
|
+
query = @noc.instance_eval do
|
69
|
+
query_string(params)
|
70
|
+
end
|
71
|
+
|
72
|
+
assert_match /date=1955/, query
|
73
|
+
assert_match /fuel=plutonium/, query
|
74
|
+
assert_match /nocname=marty/, query
|
75
|
+
assert_match /nocpass=mcSUPERfly/, query
|
76
|
+
|
77
|
+
assert_no_match /username/, query
|
78
|
+
assert_no_match /password/, query
|
79
|
+
end
|
80
|
+
|
81
|
+
test "#commit requires all :require params" do
|
82
|
+
mock_request(mock_query_url)
|
83
|
+
assert_raise(Snuggie::Errors::MissingArgument) do
|
84
|
+
@noc.instance_eval do
|
85
|
+
commit({}, :require => :fuel)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
params = { :fuel => :plutonium }
|
90
|
+
mock_request(mock_query_url(params))
|
91
|
+
assert_nothing_raised do
|
92
|
+
@noc.instance_eval do
|
93
|
+
commit(params, :require => :fuel)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
test "#commit requires one of :require_one params" do
|
99
|
+
p1 = { :date => 1955 }
|
100
|
+
mock_request(mock_query_url(p1))
|
101
|
+
assert_raise(Snuggie::Errors::MissingArgument) do
|
102
|
+
@noc.instance_eval do
|
103
|
+
commit(p1, :require_one => :fuel)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
p2 = { :date => 1955, :fuel => :plutonium }
|
108
|
+
mock_request(mock_query_url(p2))
|
109
|
+
assert_nothing_raised do
|
110
|
+
@noc.instance_eval do
|
111
|
+
commit(p2, :require_one => :fuel)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
test "#commit returns a hash if PHP.unserialize works" do
|
117
|
+
p1 = { :date => 1955 }
|
118
|
+
mock_request(mock_query_url(p1), :body => PHP.serialize(:status => :success))
|
119
|
+
res = @noc.instance_eval do
|
120
|
+
commit(p1, :require => :date)
|
121
|
+
end
|
122
|
+
assert res.has_key?('status')
|
123
|
+
assert_equal 'success', res['status']
|
124
|
+
end
|
125
|
+
|
126
|
+
test "#commit returns HTTP body if PHP.unserialize fails" do
|
127
|
+
p1 = { :date => 1955 }
|
128
|
+
mock_request(mock_query_url(p1), :body => "not a PHP serialized string")
|
129
|
+
res = @noc.instance_eval do
|
130
|
+
commit(p1, :require => :date)
|
131
|
+
end
|
132
|
+
assert_equal 'not a PHP serialized string', res
|
133
|
+
end
|
134
|
+
|
135
|
+
test "#buy_license required params" do
|
136
|
+
params = {
|
137
|
+
:ip => '127.0.0.1',
|
138
|
+
:months_to_add => 1,
|
139
|
+
:servertype => :dedicated,
|
140
|
+
:authemail => 'marty@hilldale.edu',
|
141
|
+
:autorenew => true
|
142
|
+
}
|
143
|
+
mock_request(:buy_license)
|
144
|
+
assert_raise(Snuggie::Errors::MissingArgument, "requires args") do
|
145
|
+
@noc.buy_license
|
146
|
+
end
|
147
|
+
|
148
|
+
res = @noc.buy_license(params)
|
149
|
+
assert res.is_a?(Hash)
|
150
|
+
assert_equal '1M', res['added']
|
151
|
+
assert_equal 'YES', res['autorenew']
|
152
|
+
assert_equal 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX', res['license']
|
153
|
+
assert_equal 1308062889, res['time']
|
154
|
+
assert_equal -48.0, res['bal']
|
155
|
+
assert_equal 2, res['rate']
|
156
|
+
assert_equal 99999, res['actid']
|
157
|
+
assert_equal '127.0.0.1', res['ip']
|
158
|
+
assert_equal 99999, res['lid']
|
159
|
+
assert_equal 2, res['amt']
|
160
|
+
end
|
161
|
+
|
162
|
+
test "#refund" do
|
163
|
+
mock_request(:refund)
|
164
|
+
assert_raise(Snuggie::Errors::MissingArgument, "requires actid") do
|
165
|
+
@noc.refund
|
166
|
+
end
|
167
|
+
|
168
|
+
res = @noc.refund :actid => 99999
|
169
|
+
assert res.is_a?(Hash)
|
170
|
+
assert_equal '-1M', res['added']
|
171
|
+
assert_equal 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX', res['license']
|
172
|
+
assert_equal 1308066592, res['time']
|
173
|
+
assert_equal -50.0, res['bal']
|
174
|
+
assert_equal 'refund', res['action']
|
175
|
+
assert_equal '2.00', res['rate']
|
176
|
+
assert_equal 99999, res['actid']
|
177
|
+
assert_equal 'XXXXX', res['lid']
|
178
|
+
assert_equal -2.0, res['amt']
|
179
|
+
end
|
180
|
+
|
181
|
+
test "#list_licenses" do
|
182
|
+
mock_request(:list_licenses)
|
183
|
+
res = @noc.list_licenses
|
184
|
+
assert res.is_a?(Hash)
|
185
|
+
assert_equal 1, res['num_results']
|
186
|
+
assert_equal 1, res['num_active']
|
187
|
+
assert_not_nil res['licenses']
|
188
|
+
end
|
189
|
+
|
190
|
+
test "#cancel_license" do
|
191
|
+
mock_request(:cancel_license)
|
192
|
+
assert_raise(Snuggie::Errors::MissingArgument, "requires lickey or licip") do
|
193
|
+
@noc.cancel_license
|
194
|
+
end
|
195
|
+
# TODO: fixture/test
|
196
|
+
res = @noc.cancel_license :key => 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX'
|
197
|
+
assert res.is_a?(Hash)
|
198
|
+
assert res['cancelled_license'].is_a?(Hash)
|
199
|
+
res = res['cancelled_license']
|
200
|
+
assert_equal '0', res['apiuid']
|
201
|
+
assert_equal 'XXXX', res['nocid']
|
202
|
+
assert_equal '1', res['servertype']
|
203
|
+
assert_equal 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX', res['license']
|
204
|
+
assert_equal '1308062889', res['time']
|
205
|
+
assert_equal '20110614', res['expires']
|
206
|
+
assert_equal '1', res['type']
|
207
|
+
assert_equal '0', res['last_sync']
|
208
|
+
assert_equal 'marty@hilldale.edu', res['authemail']
|
209
|
+
end
|
210
|
+
|
211
|
+
test "#invoice_details unbilled" do
|
212
|
+
mock_request(:invoice_details_unbilled)
|
213
|
+
res = @noc.invoice_details
|
214
|
+
assert res.is_a?(Hash)
|
215
|
+
assert res['actions'].is_a?(Hash)
|
216
|
+
act = res['actions'][0]
|
217
|
+
assert_equal '1M', act['added']
|
218
|
+
assert_equal 'XXXX', act['nocid']
|
219
|
+
assert_equal 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX', act['license']
|
220
|
+
assert_equal '0', act['refunded']
|
221
|
+
assert_equal '1308062889', act['time']
|
222
|
+
assert_equal '20110614', act['date']
|
223
|
+
assert_equal '2.00', act['rate']
|
224
|
+
assert_equal 'new', act['action']
|
225
|
+
assert_equal 'XXXXX', act['actid']
|
226
|
+
assert_equal '0', act['invoid']
|
227
|
+
assert_equal 'XXXXX', act['lid']
|
228
|
+
assert_equal '2.00', act['amt']
|
229
|
+
end
|
230
|
+
|
231
|
+
test "#license_logs" do
|
232
|
+
mock_request(:license_logs)
|
233
|
+
assert_raise(Snuggie::Errors::MissingArgument, "requires key") do
|
234
|
+
@noc.license_logs
|
235
|
+
end
|
236
|
+
res = @noc.license_logs :key => 'XXXXX-XXXXX-XXXXX-XXXXX'
|
237
|
+
|
238
|
+
assert res.is_a?(Hash)
|
239
|
+
assert res['actions'].is_a?(Array)
|
240
|
+
act = res['actions'].first
|
241
|
+
assert act.is_a?(Hash)
|
242
|
+
assert_equal '1M', act['added']
|
243
|
+
assert_equal 'XXXX', act['nocid']
|
244
|
+
assert_equal '0', act['refunded']
|
245
|
+
assert_equal '1308062889', act['time']
|
246
|
+
assert_equal '20110614', act['date']
|
247
|
+
assert_equal '2.00', act['rate']
|
248
|
+
assert_equal 'new', act['action']
|
249
|
+
assert_equal '0', act['invoid']
|
250
|
+
assert_equal 'XXXXX', act['lid']
|
251
|
+
assert_equal '2.00', act['amt']
|
252
|
+
lic = res['license']
|
253
|
+
assert lic.is_a?(Hash)
|
254
|
+
assert_equal '1', lic['servertype']
|
255
|
+
assert_equal 'XXXX', lic['nocid']
|
256
|
+
assert_equal '0', lic['apiuid']
|
257
|
+
assert_equal 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX', lic['license']
|
258
|
+
assert_equal '20110714', lic['expires']
|
259
|
+
assert_equal '1308062889', lic['time']
|
260
|
+
assert_equal '0', lic['last_sync']
|
261
|
+
assert_equal '1', lic['type']
|
262
|
+
assert_equal 'XXXXX', lic['lid']
|
263
|
+
assert_equal 'marty@hilldale.edu', lic['authemail']
|
264
|
+
assert_equal '1', lic['active']
|
265
|
+
end
|
266
|
+
|
267
|
+
test "#edit_ips" do
|
268
|
+
mock_request(:edit_ips)
|
269
|
+
assert_raise(Snuggie::Errors::MissingArgument, "requires ips and lid") do
|
270
|
+
@noc.edit_ips
|
271
|
+
end
|
272
|
+
res = @noc.edit_ips :ips => '127.0.0.2', :lid => 'XXXXX'
|
273
|
+
|
274
|
+
assert res.is_a?(Hash)
|
275
|
+
assert_equal 99999, res['lid']
|
276
|
+
assert res['new_ips'].is_a?(Array)
|
277
|
+
assert_equal '127.0.0.2', res['new_ips'].first
|
278
|
+
end
|
279
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
context "Snuggie" do
|
4
|
+
setup do
|
5
|
+
Snuggie.config = Snuggie::Config.new
|
6
|
+
end
|
7
|
+
|
8
|
+
test "::Version has a valid format" do
|
9
|
+
assert Snuggie::Version.match(/\d+\.\d+\.\d+/)
|
10
|
+
end
|
11
|
+
|
12
|
+
test "has class attr_accessor :config" do
|
13
|
+
assert_attr_accessor Snuggie, :config
|
14
|
+
end
|
15
|
+
|
16
|
+
test "::config defaults to Config.new" do
|
17
|
+
assert Snuggie.config.is_a?(Snuggie::Config)
|
18
|
+
end
|
19
|
+
|
20
|
+
test "::configure sets config with a block" do
|
21
|
+
Snuggie.configure do |c|
|
22
|
+
c.username = 'mcfly'
|
23
|
+
c.password = 'b4ck1nt1m3'
|
24
|
+
end
|
25
|
+
|
26
|
+
assert Snuggie.configure.is_a?(Snuggie::Config)
|
27
|
+
assert_equal Snuggie.config.username, 'mcfly'
|
28
|
+
assert_equal Snuggie.config.password, 'b4ck1nt1m3'
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'snuggie'
|
3
|
+
require 'test/unit'
|
4
|
+
require 'fakeweb'
|
5
|
+
require 'php_serialize'
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'turn'
|
9
|
+
rescue LoadError
|
10
|
+
puts "'gem install turn' for prettier test output"
|
11
|
+
end
|
12
|
+
|
13
|
+
FakeWeb.allow_net_connect = false
|
14
|
+
|
15
|
+
# test/spec/mini 3
|
16
|
+
# Based on http://gist.github.com/25455
|
17
|
+
def context(*args, &block)
|
18
|
+
return super unless (name = args.first) && block
|
19
|
+
klass = Class.new(Test::Unit::TestCase) do
|
20
|
+
def self.test(name, &block)
|
21
|
+
name = " #{name}" unless %w[: # .].include?(name[0].chr)
|
22
|
+
define_method("test: #{self.name}#{name}", &block) if block
|
23
|
+
end
|
24
|
+
def self.setup(&block) define_method(:setup, &block) end
|
25
|
+
def self.teardown(&block) define_method(:teardown, &block) end
|
26
|
+
end
|
27
|
+
(class << klass; self end).send(:define_method, :name) { name }
|
28
|
+
(class << klass; self end).send(:define_method, :to_s) { name }
|
29
|
+
klass.class_eval &block
|
30
|
+
end
|
31
|
+
|
32
|
+
def mock_request(method, options = {})
|
33
|
+
fixture = File.expand_path("../fixtures/#{method}.txt", __FILE__)
|
34
|
+
if File.exists?(fixture)
|
35
|
+
options[:body] = File.read(fixture)
|
36
|
+
end
|
37
|
+
FakeWeb.register_uri(:get, %r|^#{Snuggie::NOC::API_URL}\?.*|, options)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Asserts that the given object has an instance variable for var
|
41
|
+
#
|
42
|
+
# class Foo
|
43
|
+
# def initialize
|
44
|
+
# @bar = :bar
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# assert_instance_var(Foo.new, :bar) => passes
|
49
|
+
def assert_instance_var(obj, var)
|
50
|
+
assert_not_nil obj.instance_variable_get("@#{var}")
|
51
|
+
end
|
52
|
+
|
53
|
+
# Asserts that the given object has an attr_accessor for method
|
54
|
+
#
|
55
|
+
# class Foo
|
56
|
+
# attr_accessor :bar
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# assert_attr_accesor(Foo.new, :bar) => passes
|
60
|
+
def assert_attr_accessor(obj, method)
|
61
|
+
assert_attr_reader obj, method
|
62
|
+
assert_attr_writer obj, method
|
63
|
+
end
|
64
|
+
|
65
|
+
# Asserts that the given object has an attr_reader for method
|
66
|
+
#
|
67
|
+
# class Foo
|
68
|
+
# attr_writer :bar
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# assert_attr_reader(Foo.new, :bar) => passes
|
72
|
+
def assert_attr_reader(obj, method)
|
73
|
+
assert_respond_to obj, method
|
74
|
+
assert_equal obj.send(method), obj.instance_variable_get("@#{method}")
|
75
|
+
end
|
76
|
+
|
77
|
+
# Asserts that the given object has an attr_writer for method
|
78
|
+
#
|
79
|
+
# class Foo
|
80
|
+
# attr_writer :bar
|
81
|
+
# end
|
82
|
+
#
|
83
|
+
# assert_attr_writer(Foo.new, :bar) => passes
|
84
|
+
def assert_attr_writer(obj, method)
|
85
|
+
assert_respond_to obj, "#{method}="
|
86
|
+
end
|
87
|
+
|
88
|
+
# Asserts that the given string is a valid URL
|
89
|
+
#
|
90
|
+
# assert_valid_url('http://google.com') => passes
|
91
|
+
def assert_valid_url(string)
|
92
|
+
assert string.to_s.match(/https?:\/\/[\S]+/)
|
93
|
+
end
|
94
|
+
|
95
|
+
# From https://github.com/thoughtbot/shoulda-context/blob/master/lib/shoulda/context/assertions.rb
|
96
|
+
# Asserts that two arrays contain the same elements, the same number of times. Essentially ==, but unordered.
|
97
|
+
#
|
98
|
+
# assert_same_elements([:a, :b, :c], [:c, :a, :b]) => passes
|
99
|
+
def assert_same_elements(a1, a2, msg = nil)
|
100
|
+
[:select, :inject, :size].each do |m|
|
101
|
+
[a1, a2].each {|a| assert_respond_to(a, m, "Are you sure that #{a.inspect} is an array? It doesn't respond to #{m}.") }
|
102
|
+
end
|
103
|
+
|
104
|
+
assert a1h = a1.inject({}) { |h,e| h[e] ||= a1.select { |i| i == e }.size; h }
|
105
|
+
assert a2h = a2.inject({}) { |h,e| h[e] ||= a2.select { |i| i == e }.size; h }
|
106
|
+
|
107
|
+
assert_equal(a1h, a2h, msg)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Asserts that the given collection contains item x. If x is a regular expression, ensure that
|
111
|
+
# at least one element from the collection matches x. +extra_msg+ is appended to the error message if the assertion fails.
|
112
|
+
#
|
113
|
+
# assert_contains(['a', '1'], /\d/) => passes
|
114
|
+
# assert_contains(['a', '1'], 'a') => passes
|
115
|
+
# assert_contains(['a', '1'], /not there/) => fails
|
116
|
+
def assert_contains(collection, x, extra_msg = "")
|
117
|
+
collection = Array(collection)
|
118
|
+
msg = "#{x.inspect} not found in #{collection.to_a.inspect} #{extra_msg}"
|
119
|
+
case x
|
120
|
+
when Regexp
|
121
|
+
assert(collection.detect { |e| e =~ x }, msg)
|
122
|
+
else
|
123
|
+
assert(collection.include?(x), msg)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Asserts that the given collection does not contain item x. If x is a regular expression, ensure that
|
128
|
+
# none of the elements from the collection match x.
|
129
|
+
def assert_does_not_contain(collection, x, extra_msg = "")
|
130
|
+
collection = Array(collection)
|
131
|
+
msg = "#{x.inspect} found in #{collection.to_a.inspect} " + extra_msg
|
132
|
+
case x
|
133
|
+
when Regexp
|
134
|
+
assert(!collection.detect { |e| e =~ x }, msg)
|
135
|
+
else
|
136
|
+
assert(!collection.include?(x), msg)
|
137
|
+
end
|
138
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: snuggie
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Joshua Priddle
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-06-15 00:00:00 -04:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: php-serialize
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 1.1.0
|
25
|
+
type: :runtime
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
prerelease: false
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ~>
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 0.8.7
|
36
|
+
type: :development
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: fakeweb
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.3.0
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id003
|
49
|
+
description: " Snuggie wraps the Softaculous API in a warm, loving ruby embrace.\n"
|
50
|
+
email: jpriddle@site5.com
|
51
|
+
executables: []
|
52
|
+
|
53
|
+
extensions: []
|
54
|
+
|
55
|
+
extra_rdoc_files:
|
56
|
+
- README.markdown
|
57
|
+
files:
|
58
|
+
- Rakefile
|
59
|
+
- README.markdown
|
60
|
+
- lib/snuggie/config.rb
|
61
|
+
- lib/snuggie/errors.rb
|
62
|
+
- lib/snuggie/noc.rb
|
63
|
+
- lib/snuggie/version.rb
|
64
|
+
- lib/snuggie.rb
|
65
|
+
- test/fixtures/buy_license.txt
|
66
|
+
- test/fixtures/cancel_license.txt
|
67
|
+
- test/fixtures/edit_ips.txt
|
68
|
+
- test/fixtures/invoice_details_unbilled.txt
|
69
|
+
- test/fixtures/license_logs.txt
|
70
|
+
- test/fixtures/list_licenses.txt
|
71
|
+
- test/fixtures/refund.txt
|
72
|
+
- test/snuggie/config_test.rb
|
73
|
+
- test/snuggie/noc_test.rb
|
74
|
+
- test/snuggie_test.rb
|
75
|
+
- test/test_helper.rb
|
76
|
+
has_rdoc: true
|
77
|
+
homepage: https://github.com/site5/snuggie
|
78
|
+
licenses: []
|
79
|
+
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options:
|
82
|
+
- --charset=UTF-8
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: "0"
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: "0"
|
97
|
+
requirements: []
|
98
|
+
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 1.6.2
|
101
|
+
signing_key:
|
102
|
+
specification_version: 3
|
103
|
+
summary: Snuggie wraps the Softaculous API in a warm, loving ruby embrace
|
104
|
+
test_files: []
|
105
|
+
|