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 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