Class: RightResource::Base

Inherits:
Object show all
Defined in:
lib/right_resource/base.rb

Constant Summary collapse

@@non_rs_params =

Non RightScale parameters(ex. ec2 api request parameters)

[:cloud_id,]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attrs = {}) {|_self| ... } ⇒ Base

Returns a new instance of Base.

Yields:

  • (_self)

Yield Parameters:



352
353
354
355
356
357
358
359
360
361
362
363
# File 'lib/right_resource/base.rb', line 352

def initialize(attrs={})
  if self.class.resource_id && self.class.status_code == 201
    @id = self.class.resource_id
  else
    @id = attrs[:href].match(/\d+$/).to_s if attrs[:href]
  end

  @attributes = {}
  # sub-resource4json's key name contains '-'
  loads(attrs)
  yield self if block_given?
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_symbol, *arguments) ⇒ Object (private)

:nodoc:



475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
# File 'lib/right_resource/base.rb', line 475

def method_missing(method_symbol, *arguments) #:nodoc:
  method_name = method_symbol.to_s

  if method_name =~ /(=|\?)$/
    case $1
    when "="
      self.attributes[$`.to_sym] = arguments.first
    when "?"
      self.attributes[$`.to_sym]
    end
  else
    return self.attributes[method_symbol] if self.attributes.include?(method_symbol)
    # not set right now but we know about it
#          return nil if known_attributes.include?(method_name)
    super
  end
end

Instance Attribute Details

#attributesObject

Returns the value of attribute attributes.



323
324
325
# File 'lib/right_resource/base.rb', line 323

def attributes
  @attributes
end

#idObject

Returns the value of attribute id.



323
324
325
# File 'lib/right_resource/base.rb', line 323

def id
  @id
end

Class Method Details

.action(method, path, params = {}) ⇒ Object

RestFul Method



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/right_resource/base.rb', line 89

def action(method, path, params={})
  connection.clear
  case method
  when :get
    connection.get(path, params)
  when :post
    connection.post(path, params)
  when :put
    connection.put(path, params)
  when :delete
    connection.delete(path, params)
  else
    raise ArgumentError, "Unsupported HTTP method!!"
  end
rescue => e
  logger.error("#{e.class}: #{e.pretty_inspect}")
  logger.debug {"Backtrace:\n#{e.backtrace.pretty_inspect}"}
  nil
ensure
  logger.debug {"#{__FILE__} #{__LINE__}: #{self.class}\n#{self.pretty_inspect}\n"}
end

.collection_path(prefix_options = nil, query_options = nil) ⇒ Object

Get resource collections



239
240
241
# File 'lib/right_resource/base.rb', line 239

def collection_path(prefix_options = nil, query_options = nil)
  "#{resource_name}s#{prefix(prefix_options)}#{query_string(query_options)}"
end

.connectionObject

Get RESTFul client for HTTP Methods(Low level) and use in resource api call

Examples

conn = Server.connection
conn.get("servers?filter=nickname=server1")

ex. resource api call:

Server.index # => GET /api/acct/1/servers.json


46
47
48
49
50
51
52
53
# File 'lib/right_resource/base.rb', line 46

def connection
  if defined?(@connection) || superclass == Object
    raise ArgumentError, "Not set connection object!!" unless @connection
    @connection
  else
    superclass.connection
  end
end

.connection=(conn) ⇒ Object

Set RESTFul client with login authentication for HTTP Methods(Low level)

Examples

conn = RightResource::Connection.new do |c|
  c.(:username => "user", :password => "pass", :account => "1")
end
Deployment.connection = conn
Deployment.show(1)  # => GET /api/acct/1/deployments/1.json

RightResource::Base.connction = conn
Ec2EbsVolume.show(1)  # => GET /api/acct/1/ec2_ebs_volumes/1.json
Server.index


34
35
36
# File 'lib/right_resource/base.rb', line 34

def connection=(conn)
  @connection = conn
end

.correct_attributes(attrs) ⇒ Object

Correct attributes(Correct hash keys recursively) ‘-’(dash) is included but not ‘_’(under score) in AWS Parameter keys. On the other hand ‘_’(under score) is included in RightScale Parameter keys e.g. Hash -> Hash, Hash -> Hash



260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/right_resource/base.rb', line 260

def correct_attributes(attrs)
  return unless attrs.is_a?(Hash)

  attrs.alter_keys
  attrs.each do |key,value|  # recursive
    attrs[key] =
      case value
      when Array
        value.map do |a|
          if a.is_a?(Hash)
            v = a.dup.alter_keys rescue a.alter_keys
            correct_attributes(v)
          else
            a.dup rescue a
          end
        end
      when Hash
        v = value.dup.alter_keys rescue value.alter_keys
        correct_attributes(v)
      else
        value.dup rescue value
      end
  end
  attrs
end

.create(params = {}) ⇒ Object

Create new resource

Parameters

  • params - see Examples

Examples

params = {
  :cloud_id => 4, # {1 = us-east; 2 = eu; 3 = us-west, 4 = ap}
  :ec2_image_href => "https://my.rightscale.com/api/acct/###/multi_cloud_images/40840", # AMI image or MultiCloud image
  :nickname =>"dev703", # Instance rightscale nickname
  :instance_type => 'm1.xlarge',
  :assoicate_eip_at_launch => '0',
  :deployment_href => "https://my.rightscale.com/api/acct/###/deployments/63387",
  :ec2_availability_zone=>"ap-southeast-1b",  # (ex: 'us-east-1a', 'any')
  :ec2_ssh_key_href => "https://my.rightscale.com/api/acct/###/ec2_ssh_keys/240662",
  :ec2_security_group =>
    ["https://my.rightscale.com/api/acct/###/ec2_security_groups/170342",
    "https://my.rightscale.com/api/acct/###/ec2_security_groups/170344",
    "https://my.rightscale.com/api/acct/###/ec2_security_groups/170353"],
  :server_template_href => "https://my.rightscale.com/api/acct/###/ec2_server_templates/82665"  # rightscale servertemplate
}
server_id = Server.create(params).id
settings = Server.settings(server_id)
p settings


206
207
208
209
210
# File 'lib/right_resource/base.rb', line 206

def create(params={})
  self.new(params).tap do |resource|
    resource.save
  end
end

.destory(id) ⇒ Object

Delete resource Example:

Server.destory(1)

server = Server.index(:filter => "aws_id=i-012345")
Server.destory(server.id)


227
228
229
230
231
# File 'lib/right_resource/base.rb', line 227

def destory(id)
  path = element_path(id)
  connection.clear
  connection.delete(path)
end

.element_path(id, prefix_options = nil, query_options = nil) ⇒ Object

Get single resource



234
235
236
# File 'lib/right_resource/base.rb', line 234

def element_path(id, prefix_options = nil, query_options = nil)
  "#{resource_name}s/#{id}#{prefix(prefix_options)}#{query_string(query_options)}"
end

.formatObject

Get request and response format type object



69
70
71
# File 'lib/right_resource/base.rb', line 69

def format
  connection.format || RightResource::Formats::JsonFormat
end

.format=(mime_type_reference_or_format) ⇒ Object

Sets the format that attributes are sent and received in from a mime type reference:

Examples

Server.format = RightResource::Formats::JsonFormat
Server.show(1) # => GET /api/acct/1/servers/1.json

RightResource::Base.format = RightResource::Formats::JsonFormat
Server.index # => GET /api/acct/1/servers.json
Ec2EbsVolume.index # => GET /api/acct/1/ec2_ebs_volumes.json


64
65
66
# File 'lib/right_resource/base.rb', line 64

def format=(mime_type_reference_or_format)
  connection.format = mime_type_reference_or_format
end

.headersObject

Get response headers via RESTFul client



74
75
76
# File 'lib/right_resource/base.rb', line 74

def headers
  connection.headers || {}
end

.index(params = {}) ⇒ Object

Get resources by index method same resources support criteria like filtering.

Params

params

criteria[ex. :filter => “nickname=hoge”](Hash)

Return

Resource list(Array)

Examples

dep = Deployment.index(:filter => ["nickname=payment-dev", "nickname=payment-staging"])

test = Server.index(:filter => "nickname<>test")

Criteria unsupport

array = ServerArray.index

Get first 5 resources

server = Server.index.first(5) # see Array class

Get last resource

server = Server.index.last # see Array class

Get all operational server’s nickname

Server.index.each do |server|
  puts server.nickname if server.state = "operational"
end

Get EC2 Security Groups(aws ap = 4)

sec_grps = Ec2SecurityGroup.index(:cloud_id => "4")


139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/right_resource/base.rb', line 139

def index(params = {})
  path = "#{resource_name}s.#{format.extension}#{query_string(params)}"
  connection.clear
  result = format.decode(connection.get(path || [])).map do |resource|
    correct_attributes(resource)
  end
  instantiate_collection(result)
rescue => e
  logger.error("#{e.class}: #{e.pretty_inspect}")
  logger.debug {"Backtrace:\n#{e.backtrace.pretty_inspect}"}
  []
ensure
  logger.debug {"#{__FILE__} #{__LINE__}: #{self.class}\n#{self.pretty_inspect}\n"}
end

.loggerObject



15
16
17
18
19
20
21
# File 'lib/right_resource/base.rb', line 15

def logger
  if defined?(@logger) || superclass == Object
    @logger ||= Logger.new(STDERR).tap {|l| l.level = Logger::WARN}
  else
    superclass.logger
  end
end

.logger=(logger) ⇒ Object

Set Logger object

Examples

logger = Logger.new(STDERR)
logger.level = Logger::WARN [Default: Logger::DEBUG]
Server.logger = logger


11
12
13
# File 'lib/right_resource/base.rb', line 11

def logger=(logger)
  @logger = logger
end

.resource_idObject

Get resource id in response location header via RESTFul client(create only?)



84
85
86
# File 'lib/right_resource/base.rb', line 84

def resource_id
  connection.resource_id || nil
end

.resource_nameObject

Get resource name(equals plural of classname)



244
245
246
247
248
249
250
251
252
253
254
# File 'lib/right_resource/base.rb', line 244

def resource_name
  name = ""
  self.name.to_s.split(/::/).last.scan(/([A-Z][^A-Z]*)/).flatten.each_with_index do |str,i|
    if i > 0
      name << "_#{str.downcase}"
    else
      name << str.downcase
    end
  end
  name
end

.show(id, params = {}) ⇒ Object

Get resource

Params

params

Query Strings(Hash)

Return

Resource(Object)

Example

server_id = 1
Server.show(server_id) #=> #<Server:0x1234...>

Get deployment resource with server’s subresource

Deployment.show(1, :params => {:server_settings => "true"}) #=> #<Deployment:0x12314...>


166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/right_resource/base.rb', line 166

def show(id, params = {})
  path = element_path(id, nil, params)
  connection.clear
  result = format.decode(connection.get(path)).tap do |resource|
    correct_attributes(resource)
  end
  instantiate_record(result)
rescue => e
  logger.error("#{e.class}: #{e.pretty_inspect}")
  logger.debug {"Backtrace:\n#{e.backtrace.pretty_inspect}"}
  nil
ensure
  logger.debug {"#{__FILE__} #{__LINE__}: #{self.class}\n#{self.pretty_inspect}\n"}
end

.status_codeObject

Get response status code



79
80
81
# File 'lib/right_resource/base.rb', line 79

def status_code
  connection.status_code || nil
end

.update(id, params = {}) ⇒ Object

Update resource



213
214
215
216
217
218
219
# File 'lib/right_resource/base.rb', line 213

def update(id, params={})
  resource = self.show(id)
  return nil if resource.nil?

  resource.update_attributes(params)
  resource.save
end

Instance Method Details

#cloneObject

Duplicate resource with save



347
348
349
350
# File 'lib/right_resource/base.rb', line 347

def clone
  resource = dup
  resource.save
end

#destoryObject



412
413
414
415
# File 'lib/right_resource/base.rb', line 412

def destory
  connection.clear
  connection.delete(element_path)
end

#dupObject

Duplicate resource without save



340
341
342
343
344
# File 'lib/right_resource/base.rb', line 340

def dup
  self.class.new.tap do |resource|
    resource.attributes = @attributes.reject {|key,value| key == :href}
  end
end

#known_attributesObject

This is a list of known attributes for this resource. Either gathered from the provided schema, or from the attributes set on this instance after it has been fetched from the remote system.



335
336
337
# File 'lib/right_resource/base.rb', line 335

def known_attributes
#  self.class.known_attributes + self.attributes.keys.map(&:to_s)
end

#loads(attrs) ⇒ Object

Raises:

  • (ArgumentError)


365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
# File 'lib/right_resource/base.rb', line 365

def loads(attrs)
  raise ArgumentError, "expected an attributes Hash, got #{attrs.pretty_inspect}" unless attrs.is_a?(Hash)

  attrs.each do |key,value|  # recursive
    @attributes[key] =
      case value
      when Array
        value.map do |a|
          if a.is_a?(Hash)
            a.dup.alter_keys rescue a.alter_keys
          else
            a.dup rescue a
          end
        end
      when Hash
        value.dup.alter_keys rescue value.alter_keys
      else
        value.dup rescue value
      end
  end
  self
end

#new?Boolean Also known as: new_record?

Returns:

  • (Boolean)


403
404
405
# File 'lib/right_resource/base.rb', line 403

def new?
  id.nil?
end

#reloadObject

reload attributes of resource from the rightscale web api(discard local modified)



389
390
391
# File 'lib/right_resource/base.rb', line 389

def reload
  self.loads(self.class.show(self.id).attributes)
end

#respond_to?(method, include_priv = false) ⇒ Boolean

Returns:

  • (Boolean)


420
421
422
423
424
425
426
427
428
429
430
431
432
433
# File 'lib/right_resource/base.rb', line 420

def respond_to?(method, include_priv = false)
  method_name = method.to_s
  if attributes.nil?
    super
#      elsif known_attributes.include?(method_name)
#        true
  elsif method_name =~ /(?:=|\?)$/ && attributes.include?($`)
    true
  else
    # super must be called at the end of the method, because the inherited respond_to?
    # would return true for generated readers, even if the attribute wasn't present
    super
  end
end

#respond_to_without_attributes?Object

For checking respond_to? without searching the attributes (which is faster).



418
# File 'lib/right_resource/base.rb', line 418

alias_method :respond_to_without_attributes?, :respond_to?

#saveObject



408
409
410
# File 'lib/right_resource/base.rb', line 408

def save
  new? ? create : update
end

#schemaObject

If no schema has been defined for the class (see ActiveResource::schema=), the default automatic schema is generated from the current instance’s attributes



328
329
330
# File 'lib/right_resource/base.rb', line 328

def schema
#  self.class.schema || self.attributes
end

#update_attribute(name, value) ⇒ Object

Updates a single attribute and then saves the object.



394
395
396
397
# File 'lib/right_resource/base.rb', line 394

def update_attribute(name, value)
  self.send("#{name}=".to_sym, value)
  self.save
end

#update_attributes(attrs) ⇒ Object



399
400
401
# File 'lib/right_resource/base.rb', line 399

def update_attributes(attrs)
  loads(attrs) && save
end