studio_api 2.4.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|