studio_api 2.3.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 +93 -0
- data/Rakefile +64 -0
- data/VERSION +1 -0
- data/lib/studio_api/appliance.rb +365 -0
- data/lib/studio_api/build.rb +17 -0
- data/lib/studio_api/connection.rb +102 -0
- data/lib/studio_api/file.rb +70 -0
- data/lib/studio_api/generic_request.rb +160 -0
- data/lib/studio_api/package.rb +12 -0
- data/lib/studio_api/pattern.rb +12 -0
- data/lib/studio_api/repository.rb +35 -0
- data/lib/studio_api/rpm.rb +33 -0
- data/lib/studio_api/running_build.rb +35 -0
- data/lib/studio_api/studio_resource.rb +70 -0
- data/lib/studio_api/template_set.rb +12 -0
- data/lib/studio_api/util.rb +38 -0
- data/lib/studio_api.rb +31 -0
- data/test/appliance_test.rb +189 -0
- data/test/build_test.rb +45 -0
- data/test/connection_test.rb +21 -0
- data/test/file_test.rb +52 -0
- data/test/generic_request_test.rb +66 -0
- data/test/repository_test.rb +42 -0
- data/test/resource_test.rb +49 -0
- data/test/responses/appliance.xml +27 -0
- data/test/responses/appliances.xml +199 -0
- data/test/responses/build.xml +17 -0
- data/test/responses/builds.xml +19 -0
- data/test/responses/file.xml +12 -0
- data/test/responses/files.xml +14 -0
- data/test/responses/gpg_key.xml +25 -0
- data/test/responses/gpg_keys.xml +77 -0
- data/test/responses/repositories.xml +42 -0
- data/test/responses/repository.xml +8 -0
- data/test/responses/rpm.xml +10 -0
- data/test/responses/rpms.xml +404 -0
- data/test/responses/running_build.xml +7 -0
- data/test/responses/running_builds.xml +23 -0
- data/test/responses/software.xml +50 -0
- data/test/responses/software_installed.xml +729 -0
- data/test/responses/software_search.xml +64 -0
- data/test/responses/status-broken.xml +9 -0
- data/test/responses/status.xml +4 -0
- data/test/responses/template_sets.xml +380 -0
- data/test/rpm_test.rb +59 -0
- data/test/running_build_test.rb +50 -0
- data/test/template_set_test.rb +35 -0
- metadata +181 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
require "studio_api/studio_resource"
|
2
|
+
require "cgi"
|
3
|
+
module StudioApi
|
4
|
+
# Represents overlay files which can be loaded to appliance.
|
5
|
+
#
|
6
|
+
# Supports finding files for appliance, updating metadata, deleting, uploading and downloading.
|
7
|
+
#
|
8
|
+
# @example Find files for appliance
|
9
|
+
# StudioApi::File.find :all, :params => { :appliance_id => 1234 }
|
10
|
+
#
|
11
|
+
# @example Upload file Xorg.conf
|
12
|
+
# File.open ("/tmp/xorg.conf) { |file|
|
13
|
+
# StudioApi::File.upload file, 1234, :path => "/etc/X11",
|
14
|
+
# :filename => "Xorg.conf", :permissions => "0755",
|
15
|
+
# :owner => "root"
|
16
|
+
# }
|
17
|
+
#
|
18
|
+
# @example Update metadata
|
19
|
+
# file = StudioApi::File.find 1234
|
20
|
+
# file.owner = "root"
|
21
|
+
# file.path = "/etc"
|
22
|
+
# file.filename = "pg.conf"
|
23
|
+
# file.save
|
24
|
+
|
25
|
+
class File < ActiveResource::Base
|
26
|
+
extend StudioResource
|
27
|
+
self.element_name = "file"
|
28
|
+
|
29
|
+
# Downloads file to output. Allow downloading to stream or to path.
|
30
|
+
# @return [String] content of file
|
31
|
+
def content
|
32
|
+
rq = GenericRequest.new self.class.studio_connection
|
33
|
+
rq.get "/files/#{id.to_i}/data"
|
34
|
+
end
|
35
|
+
|
36
|
+
# Overwritte file content and keep metadata ( of course without such things like size )
|
37
|
+
# Immediatelly store new content
|
38
|
+
# @param (File,#to_s) input new content for file as String or open file
|
39
|
+
# @return [StudioApi::File] self with updated metadata
|
40
|
+
def overwrite ( content )
|
41
|
+
request_str = "/files/#{id.to_i}/data"
|
42
|
+
rq = GenericRequest.new self.class.studio_connection
|
43
|
+
response = rq.put request_str, :file => content
|
44
|
+
load Hash.from_xml(response)["file"]
|
45
|
+
end
|
46
|
+
|
47
|
+
# Uploads file to appliance
|
48
|
+
# @param (String,File) content as String or as opened File
|
49
|
+
# ( in this case its name is used as default for uploaded file name)
|
50
|
+
# @param (#to_i) appliance_id id of appliance where to upload
|
51
|
+
# @param (Hash<#to_s,#to_s>) options optional parameters, see API documentation
|
52
|
+
# @return [StudioApi::File] metadata of uploaded file
|
53
|
+
def self.upload ( content, appliance_id, options = {})
|
54
|
+
request_str = "files?appliance_id=#{appliance_id.to_i}"
|
55
|
+
options.each do |k,v|
|
56
|
+
request_str << "&#{CGI.escape k.to_s}=#{CGI.escape v.to_s}"
|
57
|
+
end
|
58
|
+
rq = GenericRequest.new studio_connection
|
59
|
+
response = rq.post request_str, :file => content
|
60
|
+
File.new Hash.from_xml(response)["file"]
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
# file uses for update parameter put
|
65
|
+
# @private
|
66
|
+
def new?
|
67
|
+
false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2010 Novell, Inc.
|
3
|
+
# All Rights Reserved.
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public License as
|
7
|
+
# published by the Free Software Foundation; version 2.1 of the license.
|
8
|
+
#
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public License
|
15
|
+
# along with this library; if not, contact Novell, Inc.
|
16
|
+
#
|
17
|
+
# To contact Novell about this file by physical or electronic mail,
|
18
|
+
# you may find current contact information at www.novell.com
|
19
|
+
|
20
|
+
require 'xmlsimple'
|
21
|
+
require 'uri'
|
22
|
+
require 'cgi'
|
23
|
+
require 'net/http'
|
24
|
+
require 'net/https'
|
25
|
+
require 'active_support'
|
26
|
+
require 'active_resource/formats'
|
27
|
+
require 'active_resource/connection'
|
28
|
+
|
29
|
+
require 'studio_api/util'
|
30
|
+
|
31
|
+
module StudioApi
|
32
|
+
# Class which use itself direct connection to studio for tasks where
|
33
|
+
# ActiveResource is not enough. For consistent api is all network exceptions
|
34
|
+
# mapped to ones used in ActiveResource.
|
35
|
+
#
|
36
|
+
# @example
|
37
|
+
# rq = StudioApi::GenericRequest.new @connection
|
38
|
+
# rq.get "/appliances"
|
39
|
+
# rq.post "/file", :file => "/etc/config"
|
40
|
+
class GenericRequest
|
41
|
+
# Creates new instance of request for given connection
|
42
|
+
# @param (StudioApi::Connection) connection information about connection
|
43
|
+
def initialize(connection)
|
44
|
+
@connection = connection
|
45
|
+
if connection.proxy
|
46
|
+
proxy = connection.proxy
|
47
|
+
@http = Net::HTTP.new(connection.uri.host, connection.uri.port,
|
48
|
+
proxy.host, proxy.port, proxy.user, proxy.password)
|
49
|
+
else
|
50
|
+
@http = Net::HTTP.new(connection.uri.host, connection.uri.port)
|
51
|
+
end
|
52
|
+
@http.read_timeout = connection.timeout
|
53
|
+
if connection.uri.scheme == "https"
|
54
|
+
@http.use_ssl = true
|
55
|
+
Connection::SSL_ATTRIBUTES.each do |attr|
|
56
|
+
@http.send :"#{attr}=", connection.ssl[attr.to_sym] if connection.ssl[attr.to_sym]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# sends get request
|
62
|
+
# @param (String) path relative path from api root
|
63
|
+
# @return (String) response body from studio
|
64
|
+
# @raise [ActiveResource::ConnectionError] when problem occur during connection
|
65
|
+
def get(path)
|
66
|
+
do_request Net::HTTP::Get.new Util.join_relative_url @connection.uri.request_uri,path
|
67
|
+
end
|
68
|
+
|
69
|
+
# sends delete request
|
70
|
+
# @param (String) path relative path from api root
|
71
|
+
# @return (String) response body from studio
|
72
|
+
# @raise [ActiveResource::ConnectionError] when problem occur during connection
|
73
|
+
def delete(path)
|
74
|
+
#Even it is not dry I want to avoid meta programming with dynamic code evaluation so code is clear
|
75
|
+
do_request Net::HTTP::Delete.new Util.join_relative_url @connection.uri.request_uri,path
|
76
|
+
end
|
77
|
+
|
78
|
+
# sends post request
|
79
|
+
# @param (String) path relative path from api root
|
80
|
+
# @param (Hash<#to_s,#to_s>,Hash<#to_s,#path>) data hash containing data to attach to body
|
81
|
+
# @return (String) response body from studio
|
82
|
+
# @raise [ActiveResource::ConnectionError] when problem occur during connection
|
83
|
+
def post(path,data={})
|
84
|
+
request = Net::HTTP::Post.new Util.join_relative_url @connection.uri.request_uri,path
|
85
|
+
set_data(request,data) unless data.empty?
|
86
|
+
do_request request
|
87
|
+
end
|
88
|
+
|
89
|
+
# sends post request
|
90
|
+
# @param (String) path relative path from api root
|
91
|
+
# @param (Hash<#to_s,#to_s>,Hash<#to_s,#path>) data hash containing data to attach to body
|
92
|
+
# @return (String) response body from studio
|
93
|
+
# @raise [ActiveResource::ConnectionError] when problem occur during connection
|
94
|
+
def put(path,data={})
|
95
|
+
request = Net::HTTP::Put.new Util.join_relative_url @connection.uri.request_uri,path
|
96
|
+
set_data(request,data) unless data.empty?
|
97
|
+
do_request request
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
def do_request(request)
|
102
|
+
request.basic_auth @connection.user, @connection.password
|
103
|
+
@http.start() do
|
104
|
+
response = @http.request request
|
105
|
+
unless response.kind_of? Net::HTTPSuccess
|
106
|
+
msg = error_message response
|
107
|
+
create_active_resource_exception response,msg
|
108
|
+
end
|
109
|
+
response.body
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
#XXX not so nice to use internal method, but better to be DRY and proper test if it works with supported rails
|
114
|
+
def create_active_resource_exception response,msg
|
115
|
+
response.instance_variable_set "@message",msg
|
116
|
+
ActiveResource::Connection.new('').send :handle_response, response
|
117
|
+
end
|
118
|
+
|
119
|
+
def error_message response
|
120
|
+
xml_parsed = XmlSimple.xml_in(response.body, {'KeepRoot' => true})
|
121
|
+
raise "Unknown error response from Studio: #{response.body}" unless xml_parsed['error']
|
122
|
+
msg = ""
|
123
|
+
xml_parsed['error'].each() {|error| msg << error['message'][0]+"\n" }
|
124
|
+
return msg
|
125
|
+
rescue RuntimeError
|
126
|
+
return response.message+"\n"+response.body
|
127
|
+
end
|
128
|
+
|
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}"
|
143
|
+
end
|
144
|
+
body << "\r\n"
|
145
|
+
end
|
146
|
+
body << "--#{boundary}--\r\n\r\n"
|
147
|
+
request.body = body
|
148
|
+
request["Content-Length"] = request.body.size
|
149
|
+
end
|
150
|
+
|
151
|
+
def mime_type(file)
|
152
|
+
case
|
153
|
+
when file =~ /\.jpe?g\z/i then 'image/jpg'
|
154
|
+
when file =~ /\.gif\z/i then 'image/gif'
|
155
|
+
when file =~ /\.png\z/i then 'image/png'
|
156
|
+
else 'application/octet-stream'
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module StudioApi
|
2
|
+
# Represents package in appliance. Used mainly as data storage.
|
3
|
+
class Package
|
4
|
+
attr_accessor :name, :version, :repository_id, :arch, :checksum, :checksum_type
|
5
|
+
def initialize name, attributes = {}
|
6
|
+
@name = name
|
7
|
+
attributes.each do |k,v|
|
8
|
+
instance_variable_set "@#{k}", v
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module StudioApi
|
2
|
+
# Represents pattern in appliance. Used mainly as data storage.
|
3
|
+
class Pattern
|
4
|
+
attr_accessor :name, :version, :repository_id, :arch
|
5
|
+
def initialize name, attributes = {}
|
6
|
+
@name = name
|
7
|
+
attributes.each do |k,v|
|
8
|
+
instance_variable_set "@#{k}", v
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "studio_api/studio_resource"
|
2
|
+
module StudioApi
|
3
|
+
# Represents available repositories for appliance.
|
4
|
+
#
|
5
|
+
# Allows finding and importing repositories.
|
6
|
+
# When using find :all then there is optional parameters for base_system and filter
|
7
|
+
#
|
8
|
+
# @example Find repository with kde for SLE11
|
9
|
+
# StudioApi::Repository.find :all, :params => { :base_system => "sle11", :filter => "kde" }
|
10
|
+
|
11
|
+
class Repository < ActiveResource::Base
|
12
|
+
extend StudioResource
|
13
|
+
|
14
|
+
undef_method :save #save is useless there
|
15
|
+
undef_method :destroy #not allowed
|
16
|
+
|
17
|
+
# Import new repository to Studio
|
18
|
+
#
|
19
|
+
# note: Repository will be available to everyone
|
20
|
+
# @param (#to_s) url to repository
|
21
|
+
# @param (#to_s) name of created repository
|
22
|
+
# @return [StudioApi::Repository] imported repository
|
23
|
+
def self.import (url, name)
|
24
|
+
response = post '',:url => url, :name => name
|
25
|
+
attrs = Hash.from_xml response.body
|
26
|
+
Repository.new attrs["repository"]
|
27
|
+
end
|
28
|
+
private
|
29
|
+
#handle special studio collection method for import
|
30
|
+
def self.custom_method_collection_url(method_name, options = {})
|
31
|
+
prefix_options, query_options = split_options(options)
|
32
|
+
"#{prefix(prefix_options)}#{collection_name}#{query_string(query_options)}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "studio_api/studio_resource"
|
2
|
+
require 'cgi'
|
3
|
+
|
4
|
+
module StudioApi
|
5
|
+
# Represents Additional rpms which can user upload to studio.
|
6
|
+
#
|
7
|
+
# Allows uploading, downloading, listing (via find) and deleting
|
8
|
+
#
|
9
|
+
# @example Delete own rpm
|
10
|
+
# rpms = StudioApi::Rpm.find :all, :params => { :base_system => "SLE11" }
|
11
|
+
# my_pac = rpms.find {|r| r.filename =~ /my_pac/ }
|
12
|
+
# my_pac.delete
|
13
|
+
class Rpm < ActiveResource::Base
|
14
|
+
extend StudioResource
|
15
|
+
undef_method :save
|
16
|
+
|
17
|
+
self.element_name = "rpm"
|
18
|
+
# Upload file to studio account (user repository)
|
19
|
+
# @param (String,File) content of rpm as String or as opened file, in which case name is used as name
|
20
|
+
# @param (#to_s) base_system for which is rpm compiled
|
21
|
+
# @return [StudioApi::Rpm] uploaded RPM
|
22
|
+
def self.upload content, base_system
|
23
|
+
response = GenericRequest.new(studio_connection).post "/rpms?base_system=#{CGI.escape base_system.to_s}", :file => content
|
24
|
+
self.new Hash.from_xml(response)["rpm"]
|
25
|
+
end
|
26
|
+
|
27
|
+
# Downloads file to specified path.
|
28
|
+
# @return [String] content of rpm
|
29
|
+
def content
|
30
|
+
GenericRequest.new(self.class.studio_connection).get "/rpms/#{id.to_i}/data"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "studio_api/studio_resource"
|
2
|
+
|
3
|
+
require "cgi"
|
4
|
+
|
5
|
+
module StudioApi
|
6
|
+
# Represents running build in studio.
|
7
|
+
#
|
8
|
+
# Provide finding builds, canceling build process or running new build
|
9
|
+
# For parameters see API documentation
|
10
|
+
# @example Run new build and then cancel it
|
11
|
+
# rb = StudioApi::RunningBuild.new(:appliance_id => 1234, :force => "true", :multi => "true")
|
12
|
+
# rb.save!
|
13
|
+
# sleep 5
|
14
|
+
# rb.cancel
|
15
|
+
class RunningBuild < ActiveResource::Base
|
16
|
+
extend StudioResource
|
17
|
+
|
18
|
+
self.element_name = "running_build"
|
19
|
+
|
20
|
+
alias_method :cancel, :destroy
|
21
|
+
|
22
|
+
private
|
23
|
+
#overwrite create as studio doesn't interact well with enclosed parameters
|
24
|
+
def create
|
25
|
+
request_str = collection_path
|
26
|
+
request_str << "?appliance_id=#{attributes.delete("appliance_id").to_i}"
|
27
|
+
attributes.each do |k,v|
|
28
|
+
request_str << "&#{CGI.escape k.to_s}=#{CGI.escape v.to_s}"
|
29
|
+
end
|
30
|
+
connection.post(request_str,"",self.class.headers).tap do |response|
|
31
|
+
load_attributes_from_response response
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require 'active_resource'
|
3
|
+
require "studio_api/util"
|
4
|
+
require "studio_api/studio_resource"
|
5
|
+
|
6
|
+
module StudioApi
|
7
|
+
# Adds ability to ActiveResource::Base (short as ARes) to easy set connection to studio in
|
8
|
+
# dynamic way, which is not so easy as ARes is designed for static values.
|
9
|
+
# Also modify a few expectation of ActiveResource to fit studio API ( like
|
10
|
+
# missing xml suffix in calls ).
|
11
|
+
#
|
12
|
+
# @example Add new Studio Resource
|
13
|
+
# # enclose it in module allows to automatic settings with Util
|
14
|
+
# module StudioApi
|
15
|
+
# class NewCoolResource < ActiveResource::Base
|
16
|
+
# extend StudioResource
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
|
20
|
+
module StudioResource
|
21
|
+
# Gets studio connection. Mostly useful internally.
|
22
|
+
# @return (StudioApi::Connection,nil) object of studio connection or nil if not
|
23
|
+
# yet set
|
24
|
+
def studio_connection
|
25
|
+
@studio_connection
|
26
|
+
end
|
27
|
+
|
28
|
+
# Takes information from connection and sets it to ActiveResource::Base.
|
29
|
+
# Also take care properly of prefix as it need to join path from site with
|
30
|
+
# api prefix like appliance/:appliance_id .
|
31
|
+
# @param (StudioApi::Connection) connection source for connection in
|
32
|
+
# activeResource
|
33
|
+
# @return (StudioApi::Connection) unmodified parameter
|
34
|
+
def studio_connection= connection
|
35
|
+
self.site = connection.uri.to_s
|
36
|
+
# there is general problem, that when specified prefix in model, it doesn't
|
37
|
+
# contain uri.path as it is not know and uri is set during runtime, so we
|
38
|
+
# must add here manually adapt prefix otherwise site.path is ommitted in
|
39
|
+
# models which has own prefix in API
|
40
|
+
unless @original_prefix
|
41
|
+
if self.prefix_source == Util.join_relative_url(connection.uri.path,'/')
|
42
|
+
@original_prefix = "/"
|
43
|
+
else
|
44
|
+
@original_prefix = self.prefix_source
|
45
|
+
end
|
46
|
+
end
|
47
|
+
self.prefix = Util.join_relative_url connection.uri.path, @original_prefix
|
48
|
+
self.user = connection.user
|
49
|
+
self.password = connection.password
|
50
|
+
self.timeout = connection.timeout
|
51
|
+
self.proxy = connection.proxy.to_s if connection.proxy
|
52
|
+
self.ssl_options = connection.ssl
|
53
|
+
@studio_connection = connection
|
54
|
+
end
|
55
|
+
|
56
|
+
# We need to overwrite the paths methods because susestudio doesn't use the
|
57
|
+
# standard .xml filename extension which is expected by ActiveResource.
|
58
|
+
def element_path(id, prefix_options = {}, query_options = nil)
|
59
|
+
prefix_options, query_options = split_options(prefix_options) if query_options.nil?
|
60
|
+
"#{prefix(prefix_options)}#{collection_name}/#{id}#{query_string(query_options)}"
|
61
|
+
end
|
62
|
+
|
63
|
+
# We need to overwrite the paths methods because susestudio doesn't use the
|
64
|
+
# standard .xml filename extension which is expected by ActiveResource.
|
65
|
+
def collection_path(prefix_options = {}, query_options = nil)
|
66
|
+
prefix_options, query_options = split_options(prefix_options) if query_options.nil?
|
67
|
+
"#{prefix(prefix_options)}#{collection_name}#{query_string(query_options)}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "studio_api/studio_resource"
|
2
|
+
|
3
|
+
module StudioApi
|
4
|
+
# Represents template sets. It is usefull when clone appliance.
|
5
|
+
# allows only reading
|
6
|
+
class TemplateSet < ActiveResource::Base
|
7
|
+
extend StudioResource
|
8
|
+
undef_method :save
|
9
|
+
undef_method :destroy
|
10
|
+
element_name = "template_set"
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module StudioApi
|
2
|
+
# Utility class for handling whole stack of Studio Api
|
3
|
+
class Util
|
4
|
+
# Set connection for all StudioApi class, so then you can use it without explicit settings
|
5
|
+
# It is useful when program use only one studio credentials
|
6
|
+
# @example
|
7
|
+
# connection = StudioApi::Connection.new ( "user", "password", "http://localhost/api")
|
8
|
+
# StudioApi::Util.configure_studio_connection connection
|
9
|
+
# appliances = StudioApi::Appliance.find :all
|
10
|
+
# @param [StudioApi::Connection] connection which is used for communication with studio
|
11
|
+
# @return [Array<Class>] return set of classes which is set
|
12
|
+
|
13
|
+
def self.configure_studio_connection connection
|
14
|
+
classes = get_all_usable_class StudioApi
|
15
|
+
classes.each {|c| c.studio_connection = connection}
|
16
|
+
end
|
17
|
+
|
18
|
+
# joins relative url for unix servers as URI.join require at least one
|
19
|
+
# absolute adress. Especially take care about only one slash otherwise studio
|
20
|
+
# returns 404.
|
21
|
+
# @param (Array<String>) args list of Strings to join
|
22
|
+
# @return (String) joined String
|
23
|
+
def self.join_relative_url(*args)
|
24
|
+
args.reduce do |base, append|
|
25
|
+
base= base[0..-2] if base.end_with? "/" #remove ending slash in base
|
26
|
+
append = append[1..-1] if append.start_with? "/" #remove leading slash in append
|
27
|
+
"#{base}/#{append}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
private
|
31
|
+
def self.get_all_usable_class (modul)
|
32
|
+
classes = modul.constants.collect{ |c| modul.const_get(c) }
|
33
|
+
classes = classes.select { |c| c.class == Class && c.respond_to?(:studio_connection=) }
|
34
|
+
inner_classes = classes.collect { |c| get_all_usable_class(c) }.flatten
|
35
|
+
classes + inner_classes
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/studio_api.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009 Novell, Inc.
|
3
|
+
# All Rights Reserved.
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public License as
|
7
|
+
# published by the Free Software Foundation; version 2.1 of the license.
|
8
|
+
#
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public License
|
15
|
+
# along with this library; if not, contact Novell, Inc.
|
16
|
+
#
|
17
|
+
# To contact Novell about this file by physical or electronic mail,
|
18
|
+
# you may find current contact information at www.novell.com
|
19
|
+
|
20
|
+
require 'studio_api/appliance'
|
21
|
+
require 'studio_api/build'
|
22
|
+
require 'studio_api/connection'
|
23
|
+
require 'studio_api/file'
|
24
|
+
require 'studio_api/generic_request'
|
25
|
+
require 'studio_api/package'
|
26
|
+
require 'studio_api/pattern'
|
27
|
+
require 'studio_api/repository'
|
28
|
+
require 'studio_api/rpm'
|
29
|
+
require 'studio_api/running_build'
|
30
|
+
require 'studio_api/studio_resource'
|
31
|
+
require 'studio_api/template_set'
|