studio_api 2.4.0 → 3.0.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 +1 -3
- data/VERSION +1 -1
- data/lib/studio_api/appliance.rb +118 -29
- data/lib/studio_api/comment.rb +26 -0
- data/lib/studio_api/gallery.rb +140 -0
- data/lib/studio_api/generic_request.rb +21 -17
- data/lib/studio_api/util.rb +11 -0
- data/lib/studio_api.rb +1 -0
- data/test/appliance_test.rb +32 -2
- data/test/gallery_test.rb +49 -0
- data/test/responses/configuration.xml +108 -0
- data/test/responses/gallery.xml +311 -0
- data/test/responses/gallery_appliance.xml +62 -0
- data/test/responses/manifest.xml +456 -0
- data/test/responses/users_0.xml +5 -0
- data/test/responses/users_1.xml +6 -0
- data/test/responses/users_2.xml +7 -0
- data/test/responses/versions.xml +12 -0
- metadata +25 -5
data/README
CHANGED
@@ -37,9 +37,7 @@ for ActiveResource error handling.
|
|
37
37
|
puts "Created appliance #{appliance.inspect}"
|
38
38
|
|
39
39
|
#add own rpm built agains SLED11_SP1
|
40
|
-
|
41
|
-
StudioApi::Rpm.upload file, "SLED11_SP1"
|
42
|
-
end
|
40
|
+
StudioApi::Rpm.upload "/home/jreidinger/rpms/kezboard-1.0-1.60.noarch.rpm", "SLED11_SP1"
|
43
41
|
# and choose it in appliance ( and of course add repository with own rpms)
|
44
42
|
appliance.add_user_repository
|
45
43
|
appliance.add_package "kezboard", :version => "1.0-1.60"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
3.0.0
|
data/lib/studio_api/appliance.rb
CHANGED
@@ -24,6 +24,46 @@ module StudioApi
|
|
24
24
|
self.element_name = "status"
|
25
25
|
end
|
26
26
|
|
27
|
+
class Configuration < ActiveResource::Base
|
28
|
+
extend StudioResource
|
29
|
+
self.element_name = "configuration"
|
30
|
+
|
31
|
+
def self.parse response
|
32
|
+
tree = XmlSimple.xml_in(response, "ForceArray" => ["tag","user","eula","autostart","database","volume"])
|
33
|
+
tree["tags"] = tree["tags"]["tag"].reduce({}){ |acc,t| acc.merge :tag => t} if tree["tags"]
|
34
|
+
tree["users"] = tree["users"]["user"]
|
35
|
+
tree["eulas"] = tree["eulas"]["eula"]
|
36
|
+
tree["autostarts"] = tree["autostarts"]["autostart"] if tree["autostarts"]
|
37
|
+
if tree["databases"]
|
38
|
+
tree["databases"]= tree["databases"]["database"]
|
39
|
+
tree["databases"].each do |d|
|
40
|
+
d["users"] = d["users"]["user"] if d["users"]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
tree["lvm"]["volumes"] = tree["lvm"]["volumes"]["volume"] if tree["lvm"] && tree["lvm"]["volumes"]
|
44
|
+
Configuration.new tree
|
45
|
+
end
|
46
|
+
|
47
|
+
def update
|
48
|
+
appliance_id = id
|
49
|
+
attributes.delete "id"
|
50
|
+
rq = GenericRequest.new self.class.studio_connection
|
51
|
+
rq.put "/appliances/#{appliance_id.to_i}/configuration", :__raw => to_xml
|
52
|
+
attributes["id"] = appliance_id
|
53
|
+
end
|
54
|
+
|
55
|
+
class Firewall < ActiveResource::Base
|
56
|
+
def to_xml(options={})
|
57
|
+
if enabled == "false"
|
58
|
+
"<firewall><enabled>false</enabled></firewall>"
|
59
|
+
else
|
60
|
+
openports_xml = open_port.reduce(""){ |acc,p| acc << "<open_port>#{p}</open_port>" } #FIXME escape name
|
61
|
+
"<firewall><enabled>true</enabled>#{openports_xml}</firewall>"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
27
67
|
# Represents repository assigned to appliance
|
28
68
|
# supports find :all and deleting from appliance
|
29
69
|
class Repository < ActiveResource::Base
|
@@ -64,9 +104,7 @@ module StudioApi
|
|
64
104
|
options[:key] = key.to_s
|
65
105
|
end
|
66
106
|
request_str = "/appliances/#{appliance_id.to_i}/gpg_keys?name=#{name}"
|
67
|
-
|
68
|
-
request_str << "&#{CGI.escape k.to_s}=#{CGI.escape v.to_s}"
|
69
|
-
end
|
107
|
+
request_str = Util.add_options request_str, options, false
|
70
108
|
response = GenericRequest.new(studio_connection).post request_str, data
|
71
109
|
self.new Hash.from_xml(response)["gpg_key"]
|
72
110
|
end
|
@@ -141,6 +179,69 @@ module StudioApi
|
|
141
179
|
rq.post "/appliances/#{id}/cmd/add_user_repository"
|
142
180
|
end
|
143
181
|
|
182
|
+
def users
|
183
|
+
request_str = "/appliances/#{id.to_i}/sharing"
|
184
|
+
response = GenericRequest.new(self.class.studio_connection).get request_str
|
185
|
+
handle_users_response response
|
186
|
+
end
|
187
|
+
|
188
|
+
def add_user name
|
189
|
+
request_str = "/appliances/#{id.to_i}/sharing/#{CGI.escape name.to_s}"
|
190
|
+
response = GenericRequest.new(self.class.studio_connection).post request_str
|
191
|
+
handle_users_response response
|
192
|
+
end
|
193
|
+
|
194
|
+
def remove_user name
|
195
|
+
request_str = "/appliances/#{id.to_i}/sharing/#{CGI.escape name.to_s}"
|
196
|
+
response = GenericRequest.new(self.class.studio_connection).delete request_str
|
197
|
+
handle_users_response response
|
198
|
+
end
|
199
|
+
|
200
|
+
def manifest_file (build, options={})
|
201
|
+
build = build.image_type if build.respond_to?(:image_type)
|
202
|
+
request_str = "/appliances/#{id.to_i}/software/manifest/#{CGI.escape build.to_s}"
|
203
|
+
request_str = Util.add_options request_str, options
|
204
|
+
GenericRequest.new(self.class.studio_connection).get request_str
|
205
|
+
end
|
206
|
+
|
207
|
+
def logo
|
208
|
+
request_str = "/appliances/#{id.to_i}/configuration/logo"
|
209
|
+
GenericRequest.new(self.class.studio_connection).get request_str
|
210
|
+
end
|
211
|
+
|
212
|
+
def logo= (logo)
|
213
|
+
request_str = "/appliances/#{id.to_i}/configuration/logo"
|
214
|
+
if logo.is_a?(IO) && logo.respond_to?(:path)
|
215
|
+
GenericRequest.new(self.class.studio_connection).post request_str, :file => logo
|
216
|
+
else
|
217
|
+
File.open(logo.to_s) do |f|
|
218
|
+
GenericRequest.new(self.class.studio_connection).post request_str, :file => f
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def background
|
224
|
+
request_str = "/appliances/#{id.to_i}/configuration/background"
|
225
|
+
GenericRequest.new(self.class.studio_connection).get request_str
|
226
|
+
end
|
227
|
+
|
228
|
+
def background= (logo)
|
229
|
+
request_str = "/appliances/#{id.to_i}/configuration/background"
|
230
|
+
if logo.is_a?(IO) && logo.respond_to?(:path)
|
231
|
+
GenericRequest.new(self.class.studio_connection).post request_str, :file => logo
|
232
|
+
else
|
233
|
+
File.open(logo.to_s) do |f|
|
234
|
+
GenericRequest.new(self.class.studio_connection).post request_str, :file => f
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def configuration
|
240
|
+
request_str = "/appliances/#{id.to_i}/configuration"
|
241
|
+
response = GenericRequest.new(self.class.studio_connection).get request_str
|
242
|
+
Configuration.parse response
|
243
|
+
end
|
244
|
+
|
144
245
|
# clones appliance or template
|
145
246
|
# @see (StudioApi::TemplateSet)
|
146
247
|
# @param (#to_i) source_id id of source appliance
|
@@ -148,9 +249,7 @@ module StudioApi
|
|
148
249
|
# @return (StudioApi::Appliance) resulted appliance
|
149
250
|
def self.clone source_id,options={}
|
150
251
|
request_str = "/appliances?clone_from=#{source_id.to_i}"
|
151
|
-
|
152
|
-
request_str << "&#{CGI.escape k.to_s}=#{CGI.escape v.to_s}"
|
153
|
-
end
|
252
|
+
request_str = Util.add_options request_str, options, false
|
154
253
|
response = GenericRequest.new(studio_connection).post request_str, options
|
155
254
|
Appliance.new Hash.from_xml(response)["appliance"]
|
156
255
|
end
|
@@ -197,14 +296,7 @@ module StudioApi
|
|
197
296
|
# @return (Array<StudioApi::Package,StudioApi::Pattern>) list of installed packages and patterns
|
198
297
|
def installed_software (options = {})
|
199
298
|
request_str = "/appliances/#{id.to_i}/software/installed"
|
200
|
-
|
201
|
-
first = true
|
202
|
-
options.each do |k,v|
|
203
|
-
separator = first ? "?" : "&"
|
204
|
-
first = false
|
205
|
-
request_str << "#{separator}#{CGI.escape k.to_s}=#{CGI.escape v.to_s}"
|
206
|
-
end
|
207
|
-
end
|
299
|
+
request_str = Util.add_options request_str, options
|
208
300
|
response = GenericRequest.new(self.class.studio_connection).get request_str
|
209
301
|
attrs = XmlSimple.xml_in response
|
210
302
|
res = []
|
@@ -222,12 +314,9 @@ module StudioApi
|
|
222
314
|
# @return (Array<StudioApi::Package,StudioApi::Pattern>) list of installed packages and patterns
|
223
315
|
def search_software (search_string,options={})
|
224
316
|
request_str = "/appliances/#{id.to_i}/software/search?q=#{CGI.escape search_string.to_s}"
|
225
|
-
|
226
|
-
request_str << "&#{CGI.escape k.to_s}=#{CGI.escape v.to_s}"
|
227
|
-
end
|
317
|
+
request_str = Util.add_options request_str, options, false
|
228
318
|
response = GenericRequest.new(self.class.studio_connection).get request_str
|
229
319
|
attrs = XmlSimple.xml_in response
|
230
|
-
return [] unless attrs["repository"]
|
231
320
|
res = []
|
232
321
|
attrs["repository"].each do |repo|
|
233
322
|
options = { "repository_id" => repo["id"].to_i }
|
@@ -241,9 +330,7 @@ module StudioApi
|
|
241
330
|
# @param (Hash<#to_s,#to_s>) options additional options, see API documentation
|
242
331
|
def rpm_content(name, options={})
|
243
332
|
request_str = "/appliances/#{id.to_i}/cmd/download_package?name=#{CGI.escape name.to_s}"
|
244
|
-
|
245
|
-
request_str << "&#{CGI.escape k.to_s}=#{CGI.escape v.to_s}"
|
246
|
-
end
|
333
|
+
request_str = Util.add_options request_str, options, false
|
247
334
|
GenericRequest.new(self.class.studio_connection).get request_str
|
248
335
|
end
|
249
336
|
|
@@ -352,16 +439,18 @@ private
|
|
352
439
|
|
353
440
|
def software_command type, options={}
|
354
441
|
request_str = "/appliances/#{id.to_i}/cmd/#{type}"
|
355
|
-
|
356
|
-
first = true
|
357
|
-
options.each do |k,v|
|
358
|
-
separator = first ? "?" : "&"
|
359
|
-
first = false
|
360
|
-
request_str << "#{separator}#{CGI.escape k.to_s}=#{CGI.escape v.to_s}"
|
361
|
-
end
|
362
|
-
end
|
442
|
+
request_str = Util.add_options request_str, options
|
363
443
|
response = GenericRequest.new(self.class.studio_connection).post request_str, options
|
364
444
|
Hash.from_xml(response)["success"]["details"]["status"]
|
365
445
|
end
|
446
|
+
|
447
|
+
def handle_users_response response
|
448
|
+
tree = XmlSimple.xml_in(response)
|
449
|
+
users = tree["read_users"][0]
|
450
|
+
return [] if users["count"].to_i == 0
|
451
|
+
users["username"].reduce([]) do |acc,u|
|
452
|
+
acc << u
|
453
|
+
end
|
454
|
+
end
|
366
455
|
end
|
367
456
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module StudioApi
|
2
|
+
# == Comment class
|
3
|
+
# Represents comment attached to published appliance in gallery.
|
4
|
+
#
|
5
|
+
# Allows to read id, time, commenter name and text of comment together
|
6
|
+
# with attached appliance
|
7
|
+
class Comment
|
8
|
+
attr_reader :id, :timestamp, :username, :text, :appliance
|
9
|
+
|
10
|
+
def initialize hash
|
11
|
+
hash.each do |k,v|
|
12
|
+
instance_variable_set :"@#{k}", v
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.parse(appliance, hash)
|
17
|
+
Comment.new hash.merge(:appliance => appliance)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Post reply to comment with text
|
21
|
+
# @param[String] text reply content
|
22
|
+
def reply text
|
23
|
+
appliance.post_comment text, :parent => id
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require "studio_api/studio_resource"
|
2
|
+
require "studio_api/generic_request"
|
3
|
+
require "studio_api/comment"
|
4
|
+
require "xmlsimple"
|
5
|
+
require "fileutils"
|
6
|
+
require 'cgi'
|
7
|
+
|
8
|
+
module StudioApi
|
9
|
+
class Gallery < ActiveResource::Base
|
10
|
+
extend StudioApi::StudioResource
|
11
|
+
self.element_name = "gallery"
|
12
|
+
|
13
|
+
class Appliance < ActiveResource::Base
|
14
|
+
extend StudioApi::StudioResource
|
15
|
+
|
16
|
+
# Gets rating details as hash
|
17
|
+
# #return[Hash] TODO
|
18
|
+
def rating
|
19
|
+
request_str = "/gallery/appliances/#{id.to_i}/rating"
|
20
|
+
response = GenericRequest.new(self.class.studio_connection).get request_str
|
21
|
+
XmlSimple.xml_in(response, "ForceArray" => false)["appliance"]
|
22
|
+
end
|
23
|
+
|
24
|
+
# Posts own rating of appliance
|
25
|
+
# @param[#to_i] value in range 0..5
|
26
|
+
# @return[Hash] TODO
|
27
|
+
def rate value
|
28
|
+
request_str = "/gallery/appliances/#{id.to_i}/rating?rating=#{value.to_i}"
|
29
|
+
response = GenericRequest.new(self.class.studio_connection).post request_str
|
30
|
+
XmlSimple.xml_in(response, "ForceArray" => false)["appliance"]
|
31
|
+
end
|
32
|
+
|
33
|
+
# Modifies appliance release notes
|
34
|
+
# @param[String] text of release notes
|
35
|
+
def release_notes= (text)
|
36
|
+
request_str = "/gallery/appliances/#{id.to_i}/version/#{CGI.escape version.to_s}"
|
37
|
+
response = GenericRequest.new(studio_connection).put request_str, :__raw => release_notes
|
38
|
+
end
|
39
|
+
|
40
|
+
# Removes appliance from gallery
|
41
|
+
def unpublish
|
42
|
+
request_str = "/gallery/appliances/#{id.to_i}/version/#{CGI.escape version.to_s}"
|
43
|
+
response = GenericRequest.new(studio_connection).delete request_str
|
44
|
+
end
|
45
|
+
|
46
|
+
# Gets all available versions of appliance in gallery
|
47
|
+
def versions
|
48
|
+
request_str = "/gallery/appliances/#{id.to_i}/versions"
|
49
|
+
response = GenericRequest.new(self.class.studio_connection).get request_str
|
50
|
+
tree = XmlSimple.xml_in response, "ForceArray" => ["version"]
|
51
|
+
return tree["appliance"]["versions"]["version"]
|
52
|
+
end
|
53
|
+
|
54
|
+
# Retrieves information about software used to create appliance
|
55
|
+
def software options = {}
|
56
|
+
request_str = "/gallery/appliances/#{id.to_i}/software"
|
57
|
+
request_str = Util.add_options request_str, options
|
58
|
+
response = GenericRequest.new(self.class.studio_connection).get request_str
|
59
|
+
#TODO parse response to something usefull
|
60
|
+
end
|
61
|
+
|
62
|
+
# Retrieves content of logo image
|
63
|
+
def logo
|
64
|
+
request_str = "/gallery/appliances/#{id.to_i}/logo"
|
65
|
+
response = GenericRequest.new(self.class.studio_connection).get request_str
|
66
|
+
end
|
67
|
+
|
68
|
+
# Retrieves content of background image
|
69
|
+
def background
|
70
|
+
request_str = "/gallery/appliances/#{id.to_i}/background"
|
71
|
+
response = GenericRequest.new(self.class.studio_connection).get request_str
|
72
|
+
end
|
73
|
+
|
74
|
+
# Starts testdrive and gets information how to use it
|
75
|
+
def testdrive options = {}
|
76
|
+
request_str = "/gallery/appliances/#{id.to_i}/testdrive"
|
77
|
+
request_str = Util.add_options request_str, options
|
78
|
+
response = GenericRequest.new(self.class.studio_connection).post request_str
|
79
|
+
tree = XmlSimple.xml_in response, "ForceArray" => false
|
80
|
+
tree["testdrive"]
|
81
|
+
end
|
82
|
+
|
83
|
+
# Retrieves all comments to appliance
|
84
|
+
# @return [Array[StudioApi::Comment]] list of comments
|
85
|
+
def comments
|
86
|
+
request_str = "/gallery/appliances/#{id.to_i}/comments"
|
87
|
+
response = GenericRequest.new(self.class.studio_connection).get request_str
|
88
|
+
tree = XmlSimple.xml_in response, "ForceArray" => ["comment"]
|
89
|
+
tree["appliance"]["comments"]["comment"].collect do |c|
|
90
|
+
Comment.parse(self,c)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Adds new comment to appliance
|
95
|
+
def post_comment text, options={}
|
96
|
+
request_str = "/gallery/appliances/#{id.to_i}/comments"
|
97
|
+
request_str = Util.add_options request_str, options
|
98
|
+
response = GenericRequest.new(self.class.studio_connection).post request_str, :__raw => text
|
99
|
+
tree = XmlSimple.xml_in response, "ForceArray" => ["comment"]
|
100
|
+
tree["appliance"]["comments"]["comment"].collect do |c|
|
101
|
+
Comment.parse(self,c)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Searches for appliance with options specified in API help
|
107
|
+
# @see http://susestudio.com/help/api/v2#65 for search specification
|
108
|
+
# @param [#to_s] type type of search
|
109
|
+
# @param [Hash[#to_s,#to_s]] options additional options
|
110
|
+
# @return TODO
|
111
|
+
def self.find_appliance type,options={}
|
112
|
+
request_str = "/gallery/appliances?#{CGI.escape type.to_s}"
|
113
|
+
request_str = Util.add_options request_str, options, false
|
114
|
+
response = GenericRequest.new(studio_connection).get request_str
|
115
|
+
tree = XmlSimple.xml_in(response,"ForceArray" => ["appliance"])["appliances"]
|
116
|
+
count = tree["pages"].to_i
|
117
|
+
page = tree["current_page"].to_i
|
118
|
+
appliances = tree["appliance"].reduce([]) do |acc,appl|
|
119
|
+
appl.each { |k,v| appl[k] = nil if v.empty? } #avoid empty string, array or hash
|
120
|
+
gappl = Gallery::Appliance.dup
|
121
|
+
gappl.studio_connection = studio_connection
|
122
|
+
acc << gappl.new(appl)
|
123
|
+
end
|
124
|
+
return :count => count, :page => page, :appliances => appliances
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.appliance id, version = nil
|
128
|
+
request_str = "/gallery/appliances/#{id.to_i}"
|
129
|
+
request_str << "/version/#{CGI.escape version.to_s}" if version
|
130
|
+
response = GenericRequest.new(studio_connection).get request_str
|
131
|
+
tree = XmlSimple.xml_in(response,"ForceArray" => ["format","account"])["appliance"]
|
132
|
+
Gallery::Appliance.new tree
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.publish_appliance id, version, release_notes
|
136
|
+
request_str = "/gallery/appliances/#{id.to_i}/version/#{CGI.escape version.to_s}"
|
137
|
+
response = GenericRequest.new(studio_connection).post request_str, :__raw => release_notes
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -127,25 +127,29 @@ module StudioApi
|
|
127
127
|
end
|
128
128
|
|
129
129
|
def set_data(request,data)
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
body
|
136
|
-
|
137
|
-
|
138
|
-
body << "
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
130
|
+
if data[:__raw]
|
131
|
+
request.body = data[:__raw]
|
132
|
+
else
|
133
|
+
boundary = Time.now.to_i.to_s(16)
|
134
|
+
request["Content-Type"] = "multipart/form-data; boundary=#{boundary}"
|
135
|
+
body = ""
|
136
|
+
data.each do |key,value|
|
137
|
+
esc_key = CGI.escape(key.to_s)
|
138
|
+
body << "--#{boundary}\r\n"
|
139
|
+
if value.respond_to?(:read) && value.respond_to?(:path)
|
140
|
+
# ::File is needed to use "Ruby" file instead this one
|
141
|
+
body << "Content-Disposition: form-data; name=\"#{esc_key}\"; filename=\"#{::File.basename(value.path)}\"\r\n"
|
142
|
+
body << "Content-Type: #{mime_type(value.path)}\r\n\r\n"
|
143
|
+
body << value.read
|
144
|
+
else
|
145
|
+
body << "Content-Disposition: form-data; name=\"#{esc_key}\"\r\n\r\n#{value}"
|
146
|
+
end
|
147
|
+
body << "\r\n"
|
143
148
|
end
|
144
|
-
body << "\r\n"
|
149
|
+
body << "--#{boundary}--\r\n\r\n"
|
150
|
+
request.body = body
|
151
|
+
request["Content-Length"] = request.body.size
|
145
152
|
end
|
146
|
-
body << "--#{boundary}--\r\n\r\n"
|
147
|
-
request.body = body
|
148
|
-
request["Content-Length"] = request.body.size
|
149
153
|
end
|
150
154
|
|
151
155
|
def mime_type(file)
|
data/lib/studio_api/util.rb
CHANGED
@@ -27,6 +27,17 @@ module StudioApi
|
|
27
27
|
"#{base}/#{append}"
|
28
28
|
end
|
29
29
|
end
|
30
|
+
|
31
|
+
def self.add_options request_str,options,first=true
|
32
|
+
unless options.empty?
|
33
|
+
options.each do |k,v|
|
34
|
+
separator = first ? "?" : "&"
|
35
|
+
first = false
|
36
|
+
request_str << "#{separator}#{CGI.escape k.to_s}=#{CGI.escape v.to_s}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
request_str
|
40
|
+
end
|
30
41
|
private
|
31
42
|
def self.get_all_usable_class (modul)
|
32
43
|
classes = modul.constants.collect{ |c| modul.const_get(c) }
|
data/lib/studio_api.rb
CHANGED
data/test/appliance_test.rb
CHANGED
@@ -25,6 +25,7 @@ REPO_ID = 6345
|
|
25
25
|
repositories_out = respond_load "repositories.xml"
|
26
26
|
gpg_keys_out = respond_load "gpg_keys.xml"
|
27
27
|
gpg_key_out = respond_load "gpg_key.xml"
|
28
|
+
conf_out = respond_load "configuration.xml"
|
28
29
|
ActiveResource::HttpMock.respond_to do |mock|
|
29
30
|
mock.get "/api/appliances", {"Authorization"=>"Basic dGVzdDp0ZXN0"},appliances_out,200
|
30
31
|
mock.get "/api/appliances/#{APPLIANCE_ID}", {"Authorization"=>"Basic dGVzdDp0ZXN0"},appliance_out,200
|
@@ -36,6 +37,7 @@ REPO_ID = 6345
|
|
36
37
|
mock.get "/api/appliances/#{APPLIANCE_ID}/gpg_keys", {"Authorization"=>"Basic dGVzdDp0ZXN0"},gpg_keys_out,200
|
37
38
|
mock.get "/api/appliances/#{APPLIANCE_ID}/gpg_keys/1976", {"Authorization"=>"Basic dGVzdDp0ZXN0"},gpg_key_out,200
|
38
39
|
mock.delete "/api/appliances/#{APPLIANCE_ID}/gpg_keys/1976", {"Authorization"=>"Basic dGVzdDp0ZXN0"},gpg_key_out,200
|
40
|
+
mock.get "/api/appliances/#{APPLIANCE_ID}/configuration", {"Authorization"=>"Basic dGVzdDp0ZXN0"},conf_out,200
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
@@ -73,6 +75,12 @@ REPO_ID = 6345
|
|
73
75
|
assert StudioApi::Appliance.clone APPLIANCE_ID
|
74
76
|
end
|
75
77
|
|
78
|
+
def test_manifest
|
79
|
+
manifest_out = respond_load "manifest.xml"
|
80
|
+
StudioApi::GenericRequest.any_instance.stubs(:get).with("/appliances/#{APPLIANCE_ID}/software/manifest/vmx").returns(manifest_out).once
|
81
|
+
assert StudioApi::Appliance.new(:id => APPLIANCE_ID).manifest_file "vmx"
|
82
|
+
end
|
83
|
+
|
76
84
|
def test_delete
|
77
85
|
assert StudioApi::Appliance.delete APPLIANCE_ID
|
78
86
|
assert StudioApi::Appliance.find(APPLIANCE_ID).destroy #same but different way
|
@@ -104,6 +112,28 @@ REPO_ID = 6345
|
|
104
112
|
assert StudioApi::Appliance.new(:id => APPLIANCE_ID).add_user_repository
|
105
113
|
end
|
106
114
|
|
115
|
+
def test_configuration
|
116
|
+
conf_out = respond_load "configuration.xml"
|
117
|
+
StudioApi::GenericRequest.any_instance.stubs(:get).with("/appliances/#{APPLIANCE_ID}/configuration").returns(conf_out).once
|
118
|
+
conf= StudioApi::Appliance.new(:id => APPLIANCE_ID).configuration
|
119
|
+
assert conf.to_xml
|
120
|
+
assert conf
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_user_repository_add
|
124
|
+
users0 = respond_load "users_0.xml"
|
125
|
+
users1 = respond_load "users_1.xml"
|
126
|
+
users2 = respond_load "users_2.xml"
|
127
|
+
StudioApi::GenericRequest.any_instance.stubs(:post).with("/appliances/#{APPLIANCE_ID}/sharing/test1").returns(users2).once
|
128
|
+
StudioApi::GenericRequest.any_instance.stubs(:get).with("/appliances/#{APPLIANCE_ID}/sharing").returns(users1).once
|
129
|
+
StudioApi::GenericRequest.any_instance.stubs(:delete).with("/appliances/#{APPLIANCE_ID}/sharing/test1").returns(users1).once
|
130
|
+
assert_equal 1, StudioApi::Appliance.new(:id => APPLIANCE_ID).users.size
|
131
|
+
assert_equal 2, StudioApi::Appliance.new(:id => APPLIANCE_ID).add_user("test1").size
|
132
|
+
assert_equal 1, StudioApi::Appliance.new(:id => APPLIANCE_ID).remove_user("test1").size
|
133
|
+
StudioApi::GenericRequest.any_instance.stubs(:get).with("/appliances/#{APPLIANCE_ID}/sharing").returns(users0).once
|
134
|
+
assert_equal 0, StudioApi::Appliance.new(:id => APPLIANCE_ID).users.size
|
135
|
+
end
|
136
|
+
|
107
137
|
def test_selected_software
|
108
138
|
software_out = respond_load "software.xml"
|
109
139
|
StudioApi::GenericRequest.any_instance.stubs(:get).with("/appliances/#{APPLIANCE_ID}/software").returns(software_out).once
|
@@ -181,8 +211,8 @@ EOF
|
|
181
211
|
|
182
212
|
def test_add_gpg_key
|
183
213
|
gpg_key_out = respond_load "gpg_key.xml"
|
184
|
-
StudioApi::GenericRequest.any_instance.stubs(:post).with("/appliances/#{APPLIANCE_ID}/gpg_keys?name=test&target=rpm&key=test",
|
185
|
-
StudioApi::GenericRequest.any_instance.stubs(:post).with("/appliances/#{APPLIANCE_ID}/gpg_keys?name=test&key=test&target=rpm",
|
214
|
+
StudioApi::GenericRequest.any_instance.stubs(:post).with("/appliances/#{APPLIANCE_ID}/gpg_keys?name=test&target=rpm&key=test",{}).returns(gpg_key_out)
|
215
|
+
StudioApi::GenericRequest.any_instance.stubs(:post).with("/appliances/#{APPLIANCE_ID}/gpg_keys?name=test&key=test&target=rpm",{}).returns(gpg_key_out)
|
186
216
|
assert StudioApi::Appliance::GpgKey.create APPLIANCE_ID, "test", "test"
|
187
217
|
assert StudioApi::Appliance.new(:id => APPLIANCE_ID).add_gpg_key "test", "test"
|
188
218
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_support'
|
3
|
+
$:.unshift File.join( File.dirname(__FILE__),'..','lib')
|
4
|
+
require 'studio_api/gallery'
|
5
|
+
require 'studio_api/connection'
|
6
|
+
require 'studio_api/generic_request'
|
7
|
+
require 'studio_api/util'
|
8
|
+
require 'active_resource/http_mock'
|
9
|
+
require 'mocha'
|
10
|
+
require 'test/unit'
|
11
|
+
|
12
|
+
class GalleryTest < Test::Unit::TestCase
|
13
|
+
APPLIANCE_ID = 130166
|
14
|
+
APPL_VERSION = "0.1.1"
|
15
|
+
def respond_load name
|
16
|
+
IO.read(File.join(File.dirname(__FILE__),"responses",name))
|
17
|
+
end
|
18
|
+
|
19
|
+
def setup
|
20
|
+
@connection = StudioApi::Connection.new("test","test","http://localhost/api/")
|
21
|
+
StudioApi::Util.configure_studio_connection @connection
|
22
|
+
end
|
23
|
+
|
24
|
+
def teardown
|
25
|
+
Mocha::Mockery.instance.stubba.unstub_all
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_find
|
29
|
+
gallery_out = respond_load "gallery.xml"
|
30
|
+
StudioApi::GenericRequest.any_instance.stubs(:get).with("/gallery/appliances?popular&per_page=10").returns(gallery_out)
|
31
|
+
out = StudioApi::Gallery.find_appliance :popular, :per_page => 10
|
32
|
+
assert 10, out[:appliances].size
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_appliance
|
36
|
+
gallery_appliance_out = respond_load "gallery_appliance.xml"
|
37
|
+
StudioApi::GenericRequest.any_instance.stubs(:get).with("/gallery/appliances/#{APPLIANCE_ID}/version/#{APPL_VERSION}").returns(gallery_appliance_out)
|
38
|
+
out = StudioApi::Gallery.appliance APPLIANCE_ID, APPL_VERSION
|
39
|
+
assert out
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_gallery_appliance_versions
|
43
|
+
versions_out = respond_load "versions.xml"
|
44
|
+
StudioApi::GenericRequest.any_instance.stubs(:get).with("/gallery/appliances/#{APPLIANCE_ID}/versions").returns(versions_out)
|
45
|
+
out = StudioApi::Gallery::Appliance.new(:id => APPLIANCE_ID).versions
|
46
|
+
assert_equal 6,out.size
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|