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 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
- File.open("/home/jreidinger/rpms/kezboard-1.0-1.60.noarch.rpm") do |file|
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
- 2.4.0
1
+ 3.0.0
@@ -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
- options.each do |k,v|
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
- options.each do |k,v|
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
- unless options.empty?
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
- options.each do |k,v|
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
- options.each do |k,v|
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
- unless options.empty?
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
- boundary = Time.now.to_i.to_s(16)
131
- request["Content-Type"] = "multipart/form-data; boundary=#{boundary}"
132
- body = ""
133
- data.each do |key,value|
134
- esc_key = CGI.escape(key.to_s)
135
- body << "--#{boundary}\r\n"
136
- if value.respond_to?(:read) && value.respond_to?(:path)
137
- # ::File is needed to use "Ruby" file instead this one
138
- body << "Content-Disposition: form-data; name=\"#{esc_key}\"; filename=\"#{::File.basename(value.path)}\"\r\n"
139
- body << "Content-Type: #{mime_type(value.path)}\r\n\r\n"
140
- body << value.read
141
- else
142
- body << "Content-Disposition: form-data; name=\"#{esc_key}\"\r\n\r\n#{value}"
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)
@@ -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
@@ -21,6 +21,7 @@ require 'studio_api/appliance'
21
21
  require 'studio_api/build'
22
22
  require 'studio_api/connection'
23
23
  require 'studio_api/file'
24
+ require 'studio_api/gallery'
24
25
  require 'studio_api/generic_request'
25
26
  require 'studio_api/package'
26
27
  require 'studio_api/pattern'
@@ -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",nil).returns(gpg_key_out)
185
- StudioApi::GenericRequest.any_instance.stubs(:post).with("/appliances/#{APPLIANCE_ID}/gpg_keys?name=test&key=test&target=rpm",nil).returns(gpg_key_out)
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