rest_connection 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +7 -0
- data/Rakefile +14 -0
- data/VERSION +1 -0
- data/config/rest_api_config.yaml.sample +7 -0
- data/examples/console.rb +10 -0
- data/examples/dev_setup.rb +26 -0
- data/examples/mysql_dev_rollback.rb +29 -0
- data/examples/relaunch_deployment.rb +45 -0
- data/examples/restart_instance_agent.rb +29 -0
- data/examples/right_scale_ec2_instances_api_test.rb +51 -0
- data/examples/run_ebs_sequence.rb +95 -0
- data/examples/run_ebs_terminate.rb +40 -0
- data/examples/run_mysql_chef_sequence.rb +43 -0
- data/examples/run_php_chef_sequence.rb +109 -0
- data/examples/set_deployment_template_href.rb +14 -0
- data/lib/rest_connection.rb +208 -0
- data/lib/rest_connection/mechanize_connection.rb +43 -0
- data/lib/rest_connection/rightscale/deployment.rb +36 -0
- data/lib/rest_connection/rightscale/executable.rb +49 -0
- data/lib/rest_connection/rightscale/instance.rb +43 -0
- data/lib/rest_connection/rightscale/right_script.rb +42 -0
- data/lib/rest_connection/rightscale/rightscale_api_base.rb +120 -0
- data/lib/rest_connection/rightscale/rightscale_api_resources.rb +22 -0
- data/lib/rest_connection/rightscale/server.rb +121 -0
- data/lib/rest_connection/rightscale/server_template.rb +31 -0
- data/lib/rest_connection/rightscale/status.rb +26 -0
- data/lib/rest_connection/ssh_hax.rb +141 -0
- data/rest_connection.gemspec +81 -0
- metadata +109 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rest_connection'
|
3
|
+
require 'trollop'
|
4
|
+
|
5
|
+
opts = Trollop::options do
|
6
|
+
opt :deployment, "deployment nickname", :type => :string, :required => true
|
7
|
+
opt :template, "server template href to set for all servers", :type => :string, :required => true
|
8
|
+
end
|
9
|
+
|
10
|
+
deployment = Deployment.find_by_nickname_speed(opts[:deployment]).first
|
11
|
+
|
12
|
+
deployment.servers.each do |s|
|
13
|
+
s.set_template(opts[:template])
|
14
|
+
end
|
@@ -0,0 +1,208 @@
|
|
1
|
+
# This file is part of RestConnection
|
2
|
+
#
|
3
|
+
# RestConnection is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# RestConnection is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with RestConnection. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
require 'net/https'
|
17
|
+
require 'rubygems'
|
18
|
+
require 'json'
|
19
|
+
require 'yaml'
|
20
|
+
require 'cgi'
|
21
|
+
require 'rest_connection/rightscale/rightscale_api_base'
|
22
|
+
require 'rest_connection/rightscale/rightscale_api_resources'
|
23
|
+
require 'logger'
|
24
|
+
|
25
|
+
module RestConnection
|
26
|
+
class Connection
|
27
|
+
# Settings is a hash of options for customizing the connection.
|
28
|
+
# settings.merge! {
|
29
|
+
# :common_headers => { "X_CUSTOM_HEADER" => "BLAH" },
|
30
|
+
# :api_url =>
|
31
|
+
# :user =>
|
32
|
+
# :pass =>
|
33
|
+
attr_accessor :settings
|
34
|
+
|
35
|
+
# RestConnection api settings configuration file:
|
36
|
+
# Settings are loaded from a yaml configuration file in users home directory.
|
37
|
+
# Copy the example config from the gemhome/config/rest_api_config.yaml.sample to ~/.rest_connection/rest_api_config.yaml
|
38
|
+
# OR to /etc/rest_connection/rest_api_config.yaml
|
39
|
+
#
|
40
|
+
def initialize(config_yaml = File.join(File.expand_path("~"), ".rest_connection", "rest_api_config.yaml"))
|
41
|
+
@@logger = nil
|
42
|
+
etc_config = File.join("#{File::SEPARATOR}etc", "rest_connection", "rest_api_config.yaml")
|
43
|
+
if File.exists?(config_yaml)
|
44
|
+
@settings = YAML::load(IO.read(config_yaml))
|
45
|
+
elsif File.exists?(etc_config)
|
46
|
+
@settings = YAML::load(IO.read(etc_config))
|
47
|
+
else
|
48
|
+
logger("\nWARNING: you must setup config file rest_api_config.yaml in #{config_yaml} or #{etc_config}")
|
49
|
+
logger("WARNING: see GEM_HOME/rest_connection/config/rest_api_config.yaml for example config")
|
50
|
+
@settings = {}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Main HTTP connection loop. Common settings are set here, then we yield(BASE_URI, OPTIONAL_HEADERS) to other methods for each type of HTTP request: GET, PUT, POST, DELETE
|
55
|
+
#
|
56
|
+
# The block must return a Net::HTTP Request. You have a chance to taylor the request inside the block that you pass by modifying the url and headers.
|
57
|
+
#
|
58
|
+
# rest_connect do |base_uri, headers|
|
59
|
+
# headers.merge! {:my_header => "blah"}
|
60
|
+
# Net::HTTP::Get.new(base_uri, headers)
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
def rest_connect(&block)
|
64
|
+
uri = URI.parse(@settings[:api_url])
|
65
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
66
|
+
if uri.scheme == 'https'
|
67
|
+
http.use_ssl = true
|
68
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
69
|
+
end
|
70
|
+
headers = @settings[:common_headers]
|
71
|
+
http.start do |http|
|
72
|
+
req = yield(uri, headers)
|
73
|
+
req.basic_auth(@settings[:user], @settings[:pass]) if @settings[:user]
|
74
|
+
logger("#{req.method}: #{req.path}")
|
75
|
+
logger("\trequest body: #{req.body}") if req.body
|
76
|
+
response, body = http.request(req)
|
77
|
+
handle_response(response)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# connection.get("/root/login", :test_header => "x", :test_header2 => "y")
|
82
|
+
# href = "/api/base_new" if this begins with a slash then the url will be used as absolute path.
|
83
|
+
# href = "servers" this will be concat'd on to the api_url from the settings
|
84
|
+
# additional_parameters = Hash or String of parameters to pass to HTTP::Get
|
85
|
+
def get(href, additional_parameters = "")
|
86
|
+
rest_connect do |base_uri,headers|
|
87
|
+
href = "#{base_uri}/#{href}" unless begins_with_slash(href)
|
88
|
+
new_path = URI.escape(href + '.js?' + requestify(additional_parameters))
|
89
|
+
Net::HTTP::Get.new(new_path, headers)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# connection.post(server_url + "/start")
|
94
|
+
#
|
95
|
+
# href = "/api/base_new" if this begins with a slash then the url will be used as absolute path.
|
96
|
+
# href = "servers" this will be concat'd on to the api_url from the settings
|
97
|
+
# additional_parameters = Hash or String of parameters to pass to HTTP::Post
|
98
|
+
def post(href, additional_parameters = {})
|
99
|
+
rest_connect do |base_uri, headers|
|
100
|
+
href = "#{base_uri}/#{href}" unless begins_with_slash(href)
|
101
|
+
res = Net::HTTP::Post.new(href , headers)
|
102
|
+
unless additional_parameters.empty?
|
103
|
+
res.set_content_type('application/json')
|
104
|
+
res.body = additional_parameters.to_json
|
105
|
+
end
|
106
|
+
#res.set_form_data(additional_parameters, '&')
|
107
|
+
res
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# connection.put(server_url + "/start")
|
112
|
+
#
|
113
|
+
# href = "/api/base" if this begins with a slash then the url will be used as absolute path.
|
114
|
+
# href = "servers" this will be concat'd on to the api_url from the settings
|
115
|
+
# additional_parameters = Hash or String of parameters to pass to HTTP::Put
|
116
|
+
def put(href, additional_parameters = {})
|
117
|
+
rest_connect do |base_uri, headers|
|
118
|
+
href = "#{base_uri}/#{href}" unless begins_with_slash(href)
|
119
|
+
new_path = URI.escape(href)
|
120
|
+
req = Net::HTTP::Put.new(new_path, headers)
|
121
|
+
req.set_content_type('application/json')
|
122
|
+
req.body = additional_parameters.to_json
|
123
|
+
req
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# connection.delete(server_url)
|
128
|
+
#
|
129
|
+
# href = "/api/base_new" if this begins with a slash then the url will be used as absolute path.
|
130
|
+
# href = "servers" this will be concat'd on to the api_url from the settings
|
131
|
+
# additional_parameters = Hash or String of parameters to pass to HTTP::Delete
|
132
|
+
def delete(href, additional_parameters = {})
|
133
|
+
rest_connect do |base_uri, headers|
|
134
|
+
href = "#{base_uri}/#{href}" unless begins_with_slash(href)
|
135
|
+
new_path = URI.escape(href)
|
136
|
+
req = Net::HTTP::Delete.new(href, headers)
|
137
|
+
req.set_content_type('application/json')
|
138
|
+
req.body = additional_parameters.to_json
|
139
|
+
req
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# handle_response
|
144
|
+
# res = HTTP response
|
145
|
+
#
|
146
|
+
# decoding and post processing goes here. This is where you may need some customization if you want to handle the response differently (or not at all!). Luckily it's easy to modify based on this handler.
|
147
|
+
def handle_response(res)
|
148
|
+
if res.code.to_i == 201
|
149
|
+
return res['Location']
|
150
|
+
elsif [200,203,204].detect { |d| d == res.code.to_i }
|
151
|
+
if res.body
|
152
|
+
begin
|
153
|
+
return JSON.load(res.body)
|
154
|
+
rescue => e
|
155
|
+
return res
|
156
|
+
end
|
157
|
+
else
|
158
|
+
return res
|
159
|
+
end
|
160
|
+
else
|
161
|
+
raise "invalid response HTTP code: #{res.code.to_i}, #{res.code}, #{res.body}"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def begins_with_slash(href)
|
166
|
+
href =~ /^\//
|
167
|
+
end
|
168
|
+
|
169
|
+
def logger(message)
|
170
|
+
init_message = "Initializing Logging using "
|
171
|
+
if @@logger.nil?
|
172
|
+
if @settings[:log_file]
|
173
|
+
@@logger = Logger.new(@settings[:log_file])
|
174
|
+
init_message += @settings[:log_file]
|
175
|
+
elsif ENV['REST_CONNECTION_LOG']
|
176
|
+
@@logger = Logger.new(ENV['REST_CONNECTION_LOG'])
|
177
|
+
init_message += ENV['REST_CONNECTION_LOG']
|
178
|
+
else @settings[:log_file]
|
179
|
+
@@logger = Logger.new(STDOUT)
|
180
|
+
init_message += "STDOUT"
|
181
|
+
end
|
182
|
+
STDOUT.puts init_message
|
183
|
+
end
|
184
|
+
|
185
|
+
@@logger.info(message)
|
186
|
+
end
|
187
|
+
|
188
|
+
# used by requestify to build parameters strings
|
189
|
+
def name_with_prefix(prefix, name)
|
190
|
+
prefix ? "#{prefix}[#{name}]" : name.to_s
|
191
|
+
end
|
192
|
+
|
193
|
+
# recursive method builds CGI escaped strings from Hashes, Arrays and strings of parameters.
|
194
|
+
def requestify(parameters, prefix=nil)
|
195
|
+
if Hash === parameters
|
196
|
+
return nil if parameters.empty?
|
197
|
+
parameters.map { |k,v| requestify(v, name_with_prefix(prefix, k)) }.join("&")
|
198
|
+
elsif Array === parameters
|
199
|
+
parameters.map { |v| requestify(v, name_with_prefix(prefix, "")) }.join("&")
|
200
|
+
elsif prefix.nil?
|
201
|
+
parameters
|
202
|
+
else
|
203
|
+
"#{CGI.escape(prefix)}=#{CGI.escape(parameters.to_s)}"
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'mechanize'
|
2
|
+
require 'logger'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module MechanizeConnection
|
6
|
+
module Connection
|
7
|
+
|
8
|
+
# creates/returns global mechanize agent
|
9
|
+
def agent
|
10
|
+
@@agent ||= WWW::Mechanize.new do |a|
|
11
|
+
a.log = Logger.new(STDOUT)
|
12
|
+
a.log.level = Logger::INFO
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# creates/returns global mechanize agent
|
17
|
+
def self.agent
|
18
|
+
@@agent ||= WWW::Mechanize.new do |a|
|
19
|
+
a.log = Logger.new(STDOUT)
|
20
|
+
a.log.level = Logger::INFO
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# login to rightscale dashboard /sessions/new using rest connection user and pass
|
25
|
+
def wind_monkey
|
26
|
+
base_url = URI.parse(connection.settings[:api_url])
|
27
|
+
base_url.path = "/"
|
28
|
+
if agent.cookie_jar.empty?(base_url)
|
29
|
+
agent.user_agent_alias = 'Mac Safari'
|
30
|
+
# Login
|
31
|
+
base_url = URI.parse(connection.settings[:api_url])
|
32
|
+
agent.user_agent_alias = 'Mac Safari'
|
33
|
+
# Login
|
34
|
+
base_url.path = "/sessions/new"
|
35
|
+
login_page = agent.get(base_url)
|
36
|
+
login_form = login_page.forms.first
|
37
|
+
login_form.email = connection.settings[:user]
|
38
|
+
login_form.password = connection.settings[:pass]
|
39
|
+
agent.submit(login_form, login_form.buttons.first)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# This file is part of RestConnection
|
2
|
+
#
|
3
|
+
# RestConnection is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# RestConnection is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with RestConnection. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
class Deployment < RightScale::Api::Base
|
17
|
+
def set_input(name, value)
|
18
|
+
deploy_href = URI.parse(self.href)
|
19
|
+
connection.put(deploy_href.path, :deployment => {:parameters => {name => value} })
|
20
|
+
end
|
21
|
+
|
22
|
+
def servers_no_reload
|
23
|
+
server_list = []
|
24
|
+
@params['servers'].each do |s|
|
25
|
+
server_list << Server.new(s)
|
26
|
+
end
|
27
|
+
return server_list
|
28
|
+
end
|
29
|
+
|
30
|
+
def servers
|
31
|
+
# this populates extra information about the servers
|
32
|
+
servers_no_reload.each do |s|
|
33
|
+
s.reload
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class Executable < RightScale::Api::Base
|
2
|
+
|
3
|
+
# executable can be EITHER a right_script or recipe
|
4
|
+
# executable example params format:
|
5
|
+
# can have recipes AND right_scripts
|
6
|
+
# @params =
|
7
|
+
# { :recipe =>
|
8
|
+
# :position => 12,
|
9
|
+
# :apply => "operational",
|
10
|
+
# :right_script => { "href" => "http://blah",
|
11
|
+
# "name" => "blah"
|
12
|
+
# ...
|
13
|
+
# }
|
14
|
+
|
15
|
+
def recipe?
|
16
|
+
if self["recipe"].nil? && right_script['href']
|
17
|
+
return false
|
18
|
+
end
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def right_script?
|
23
|
+
if self["recipe"].nil? && right_script['href']
|
24
|
+
return true
|
25
|
+
end
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
def name
|
30
|
+
if right_script?
|
31
|
+
return right_script.name
|
32
|
+
else
|
33
|
+
return recipe
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def href
|
38
|
+
if right_script?
|
39
|
+
return right_script.href
|
40
|
+
else
|
41
|
+
#recipes do not have hrefs, only names
|
42
|
+
return recipe
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def right_script
|
47
|
+
RightScript.new(@params['right_script'])
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# This file is part of RestConnection
|
2
|
+
#
|
3
|
+
# RestConnection is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# RestConnection is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with RestConnection. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
# This is an instance facing api and can only be used with
|
17
|
+
# an authentication URL normally found in the instance's userdata called
|
18
|
+
# RS_API_URL
|
19
|
+
class Instance < RightScale::Api::Base
|
20
|
+
#def create_ebs_volume_from_snap(snap_aws_id)
|
21
|
+
# connection.post('create_ebs_volume.js', :aws_id => snap_aws_id )
|
22
|
+
#end
|
23
|
+
|
24
|
+
def attach_ebs_volume(params)
|
25
|
+
connection.put('attach_ebs_volume.js', params)
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_ebs_snapshot(params)
|
29
|
+
connection.post('create_ebs_snapshot.js', params)
|
30
|
+
end
|
31
|
+
|
32
|
+
def detach_ebs_volume(params)
|
33
|
+
connection.put('detach_ebs_volume.js', params)
|
34
|
+
end
|
35
|
+
|
36
|
+
def delete_ebs_volume(params)
|
37
|
+
connection.delete('delete_ebs_volume.js', params)
|
38
|
+
end
|
39
|
+
|
40
|
+
def create_ebs_volume(params)
|
41
|
+
connection.post('create_ebs_volume.js', params)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# This file is part of RestConnection
|
2
|
+
#
|
3
|
+
# RestConnection is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# RestConnection is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with RestConnection. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
|
17
|
+
class RightScript < RightScale::Api::Base
|
18
|
+
def self.from_yaml(yaml)
|
19
|
+
scripts = []
|
20
|
+
x = YAML.load(yaml)
|
21
|
+
x.keys.each do |script|
|
22
|
+
scripts << self.new('href' => "right_scripts/#{script}", 'name' => x[script].ivars['name'])
|
23
|
+
end
|
24
|
+
scripts
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.from_instance_info(file = "/var/spool/ec2/rs_cache/info.yml")
|
28
|
+
scripts = []
|
29
|
+
if File.exists?(file)
|
30
|
+
x = YAML.load(IO.read(file))
|
31
|
+
elsif File.exists?(File.join(File.dirname(__FILE__),'info.yml'))
|
32
|
+
x = YAML.load(IO.read(File.join(File.dirname(__FILE__),'info.yml')))
|
33
|
+
else
|
34
|
+
return nil
|
35
|
+
end
|
36
|
+
x.keys.each do |script|
|
37
|
+
scripts << self.new('href' => "right_scripts/#{script}", 'name' => x[script].ivars['name'])
|
38
|
+
end
|
39
|
+
scripts
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# This file is part of RestConnection
|
2
|
+
#
|
3
|
+
# RestConnection is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# RestConnection is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with RestConnection. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
require 'rest_connection/mechanize_connection'
|
17
|
+
require 'activesupport'
|
18
|
+
|
19
|
+
module RightScale
|
20
|
+
module Api
|
21
|
+
class Base
|
22
|
+
include MechanizeConnection::Connection
|
23
|
+
# The params hash of attributes for direct manipulation
|
24
|
+
attr_accessor :params
|
25
|
+
|
26
|
+
def self.connection()
|
27
|
+
@@connection ||= RestConnection::Connection.new
|
28
|
+
end
|
29
|
+
def connection()
|
30
|
+
@@connection ||= RestConnection::Connection.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(params = {})
|
34
|
+
@params = params
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.resource_plural_name
|
38
|
+
self.to_s.underscore.pluralize
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.resource_singluar_name
|
42
|
+
self.to_s.underscore
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.find_all
|
46
|
+
a = Array.new
|
47
|
+
connection.get(self.resource_plural_name).each do |object|
|
48
|
+
a << self.new(object)
|
49
|
+
end
|
50
|
+
return a
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.find_by_nickname(nickname)
|
54
|
+
self.find_all.select do |s|
|
55
|
+
s.nickname == nickname
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def reload
|
60
|
+
uri = URI.parse(self.href)
|
61
|
+
@params ? @params.merge!(connection.get(uri.path)) : @params = connection.get(uri.path)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.find(href)
|
65
|
+
uri = URI.parse(href)
|
66
|
+
self.new(connection.get(uri.path))
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.find_by_id(id)
|
70
|
+
self.new(connection.get(self.resource_plural_name + "/#{id}"))
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.create(opts)
|
74
|
+
location = connection.post(self.resource_plural_name, self.resource_singluar_name.to_sym => opts)
|
75
|
+
self.new('href' => location)
|
76
|
+
end
|
77
|
+
|
78
|
+
# filter is only implemented on some api endpoints
|
79
|
+
def self.find_by_nickname_speed(nickname)
|
80
|
+
self.find_with_filter('nickname' => nickname)
|
81
|
+
end
|
82
|
+
|
83
|
+
# filter is only implemented on some api endpoints
|
84
|
+
def self.find_with_filter(filter = {})
|
85
|
+
filter_params = ""
|
86
|
+
filter.each {|key,val| filter_params += "filter[]=#{key}=#{val}&"}
|
87
|
+
a = Array.new
|
88
|
+
connection.get(self.resource_plural_name, filter_params).each do |object|
|
89
|
+
a << self.new(object)
|
90
|
+
end
|
91
|
+
return a
|
92
|
+
end
|
93
|
+
|
94
|
+
def destroy
|
95
|
+
my_href = URI.parse(self.href)
|
96
|
+
connection.delete(my_href.path)
|
97
|
+
end
|
98
|
+
|
99
|
+
# the following two methods are used to access the @params hash in a friendly way
|
100
|
+
def method_missing(method_name, *args)
|
101
|
+
if @params[method_name.to_s]
|
102
|
+
return @params[method_name.to_s]
|
103
|
+
elsif @params[method_name.to_s.gsub(/_/,'-')]
|
104
|
+
return @params[method_name.to_s.gsub(/_/,'-')]
|
105
|
+
else
|
106
|
+
raise "called unknown method #{method_name} with #{args.inspect}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def [](name)
|
111
|
+
if @params[name]
|
112
|
+
return @params[name]
|
113
|
+
else
|
114
|
+
return nil
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|