Class: RedfishClient::Resource
- Inherits:
-
Object
- Object
- RedfishClient::Resource
- Defined in:
- lib/redfish_client/resource.rb
Overview
Resource is basic building block of Redfish client and serves as a container for the data that is retrieved from the Redfish service.
When we interact with the Redfish service, resource will wrap the data retrieved from the service API and offer us dot-notation accessors for values stored.
Resource will also load any sub-resource on demand when we access it.
For example, if we have a root Redfish resource stored in root,
accessing root.SessionService will automatically fetch the appropriate
resource from the API.
In order to reduce the amount of requests being sent to the service, resource can also utilise caching connector. If we would like to get fresh values from the service, #refresh call will flush the cache and retrieve fresh data from the remote.
Direct Known Subclasses
Defined Under Namespace
Classes: NoODataId, NoResource, Timeout
Instance Attribute Summary collapse
-
#headers ⇒ Hash
readonly
Headers, returned from the service when resource has been constructed.
-
#raw ⇒ Hash
readonly
Raw data that has been used to construct resource by either fetching it from the remote API or by being passed-in as a parameter to constructor.
Instance Method Summary collapse
-
#[](attr) ⇒ Object
Access resource content.
-
#delete(field: "@odata.id", path: nil, payload: nil, headers: nil) ⇒ RedfishClient::Response
Issue a DELETE requests to the endpoint of the resource.
-
#dig(*keys) ⇒ Object
Safely access nested resource content.
-
#etag ⇒ String?
Get ETag from the response headers or resource property.
-
#get(field: "@odata.id", path: nil, headers: nil) ⇒ RedfishClient::Response
Issue a GET requests to the selected endpoint.
-
#initialize(connector, oid: nil, raw: nil) ⇒ Resource
constructor
Create new resource.
-
#key?(name) ⇒ Boolean
Test if resource contains required key.
-
#method_missing(symbol, *_args, &_block) ⇒ Object
Convenience access for resource data.
-
#patch(field: "@odata.id", path: nil, payload: nil, headers: nil, etag: nil) ⇒ RedfishClient::Response
Issue a PATCH requests to the selected endpoint.
-
#patch_if_match(payload, field: "@odata.id", path: nil, headers: nil) ⇒ RedfishClient::Response
Issue a PATCH request using the ETag from this resource.
-
#post(field: "@odata.id", path: nil, payload: nil, headers: nil) ⇒ RedfishClient::Response
Issue a POST requests to the selected endpoint.
-
#refresh ⇒ Object
Refresh resource content from the API.
-
#request(method, field, path, payload = nil, headers = nil, etag = nil) ⇒ RedfishClient::Response
Issue a requests to the selected endpoint.
- #respond_to_missing?(symbol, include_private = false) ⇒ Boolean
-
#to_s ⇒ String
Pretty-print the wrapped content.
-
#wait(response, retries: 10, delay: 1) ⇒ RedfishClient::Response
Wait for the potentially async operation to terminate.
Constructor Details
#initialize(connector, oid: nil, raw: nil) ⇒ Resource
Create new resource.
Resource can be created either by passing in OpenData identifier or supplying the content (hash). In the first case, connector will be used to fetch the resource data. In the second case, resource only wraps the passed-in hash and does no fetching.
74 75 76 77 78 79 80 81 |
# File 'lib/redfish_client/resource.rb', line 74 def initialize(connector, oid: nil, raw: nil) @connector = connector if oid initialize_from_service(oid) else @raw = raw end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(symbol, *_args, &_block) ⇒ Object
Convenience access for resource data.
Calling resource.Value is exactly the same as resource["Value"].
139 140 141 |
# File 'lib/redfish_client/resource.rb', line 139 def method_missing(symbol, *_args, &_block) self[symbol.to_s] end |
Instance Attribute Details
#headers ⇒ Hash (readonly)
Headers, returned from the service when resource has been constructed.
37 38 39 |
# File 'lib/redfish_client/resource.rb', line 37 def headers @headers end |
#raw ⇒ Hash (readonly)
Raw data that has been used to construct resource by either fetching it from the remote API or by being passed-in as a parameter to constructor.
43 44 45 |
# File 'lib/redfish_client/resource.rb', line 43 def raw @raw end |
Instance Method Details
#[](attr) ⇒ Object
Access resource content.
This function offers a way of accessing resource data in the same way that hash exposes its content.
111 112 113 |
# File 'lib/redfish_client/resource.rb', line 111 def [](attr) build_resource(raw[attr]) end |
#delete(field: "@odata.id", path: nil, payload: nil, headers: nil) ⇒ RedfishClient::Response
Issue a DELETE requests to the endpoint of the resource.
If the resource has no @odata.id field, NoODataId error will be
raised, since deleting non-networked resources makes no sense and
probably indicates bug in library consumer.
291 292 293 |
# File 'lib/redfish_client/resource.rb', line 291 def delete(field: "@odata.id", path: nil, payload: nil, headers: nil) request(:delete, field, path, payload, headers) end |
#dig(*keys) ⇒ Object
Safely access nested resource content.
This function is an equivalent of safe navigation operator that can be used with arbitrary keys.
Calling res.dig("a", "b", "c") is equivalent to res.a&.b&.c and
res["a"] && res["a"]["b"] && res["a"]["b"]["c"].
124 125 126 |
# File 'lib/redfish_client/resource.rb', line 124 def dig(*keys) keys.reduce(self) { |a, k| a.nil? ? nil : a[k] } end |
#etag ⇒ String?
Get ETag from the response headers or resource property.
Redfish services may provide ETag in two ways:
- HTTP ETag header (preferred)
- @odata.etag property in the resource (fallback)
This method checks both locations, prioritizing the HTTP header.
54 55 56 57 58 59 60 |
# File 'lib/redfish_client/resource.rb', line 54 def etag # Prefer HTTP header (used for If-Match header) return @headers["etag"] if @headers&.key?("etag") # Fallback to @odata.etag property raw["@odata.etag"] end |
#get(field: "@odata.id", path: nil, headers: nil) ⇒ RedfishClient::Response
Issue a GET requests to the selected endpoint.
By default, GET request will be sent to the path, stored in @odata.id
field. Source field can be changed by specifying the field parameter
when calling this function. Specifying the path argument will bypass
the field lookup altogether and issue a GET request directly to the
selected path.
If the resource has no lookup field, NoODataId error will be raised, since posting to non-networked resources makes no sense and probably indicates bug in library consumer.
206 207 208 |
# File 'lib/redfish_client/resource.rb', line 206 def get(field: "@odata.id", path: nil, headers: nil) request(:get, field, path, nil, headers) end |
#key?(name) ⇒ Boolean
Test if resource contains required key.
132 133 134 |
# File 'lib/redfish_client/resource.rb', line 132 def key?(name) raw.key?(name.to_s) end |
#patch(field: "@odata.id", path: nil, payload: nil, headers: nil, etag: nil) ⇒ RedfishClient::Response
Issue a PATCH requests to the selected endpoint.
Works exactly the same as the #post method, but issued a PATCH request to the server.
247 248 249 |
# File 'lib/redfish_client/resource.rb', line 247 def patch(field: "@odata.id", path: nil, payload: nil, headers: nil, etag: nil) request(:patch, field, path, payload, headers, etag) end |
#patch_if_match(payload, field: "@odata.id", path: nil, headers: nil) ⇒ RedfishClient::Response
Issue a PATCH request using the ETag from this resource.
This is a convenience method that uses the ETag value obtained when
this resource was retrieved from the service. The resource must be
fetched via GET (e.g., using client.find()) before calling this
method, so that the ETag is available in the response headers.
If no ETag is present in the headers, this method will perform a regular PATCH without the If-Match header.
274 275 276 277 |
# File 'lib/redfish_client/resource.rb', line 274 def patch_if_match(payload, field: "@odata.id", path: nil, headers: nil) current_etag = etag patch(field: field, path: path, payload: payload, headers: headers, etag: current_etag) end |
#post(field: "@odata.id", path: nil, payload: nil, headers: nil) ⇒ RedfishClient::Response
Issue a POST requests to the selected endpoint.
By default, POST request will be sent to the path, stored in @odata.id
field. Source field can be changed by specifying the field parameter
when calling this function. Specifying the path argument will bypass
the field lookup altogether and POST directly to the requested path.
In order to avoid having to manually serialize data to JSON, this function call takes Hash as a payload and encodes it before sending it to the endpoint.
If the resource has no lookup field, NoODataId error will be raised, since posting to non-networked resources makes no sense and probably indicates bug in library consumer.
231 232 233 |
# File 'lib/redfish_client/resource.rb', line 231 def post(field: "@odata.id", path: nil, payload: nil, headers: nil) request(:post, field, path, payload, headers) end |
#refresh ⇒ Object
Refresh resource content from the API
Caling this method will ensure that the resource data is in sync with the Redfish API, invalidating any caches as necessary.
299 300 301 302 303 304 305 306 |
# File 'lib/redfish_client/resource.rb', line 299 def refresh return unless self["@odata.id"] # TODO(@tadeboro): raise more sensible exception if resource cannot be # refreshed. @connector.reset(self["@odata.id"]) initialize_from_service(self["@odata.id"]) end |
#request(method, field, path, payload = nil, headers = nil, etag = nil) ⇒ RedfishClient::Response
Issue a requests to the selected endpoint.
By default, request will be sent to the path, stored in @odata.id
field. Source field can be changed by specifying the field parameter
when calling this function. Specifying the path argument will bypass
the field lookup altogether and issue a request directly to the selected
path.
If the resource has no lookup field, NoODataId error will be raised, since posting to non-networked resources makes no sense and probably indicates bug in library consumer.
174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/redfish_client/resource.rb', line 174 def request(method, field, path, payload = nil, headers = nil, etag = nil) @connector.add_headers(headers) if headers&.any? target_path = get_path(field, path) # Use etag-aware patch method when etag is provided if method == :patch && etag # Forward ETag value from caller to Connector#patch as keyword argument @connector.patch(target_path, payload, etag: etag) else @connector.request(method, target_path, payload) end ensure @connector.remove_headers(headers) if headers&.any? end |
#respond_to_missing?(symbol, include_private = false) ⇒ Boolean
143 144 145 |
# File 'lib/redfish_client/resource.rb', line 143 def respond_to_missing?(symbol, include_private = false) key?(symbol.to_s) || super end |
#to_s ⇒ String
Pretty-print the wrapped content.
150 151 152 |
# File 'lib/redfish_client/resource.rb', line 150 def to_s JSON.pretty_generate(raw) end |
#wait(response, retries: 10, delay: 1) ⇒ RedfishClient::Response
Wait for the potentially async operation to terminate
Note that this can be safely called on response from non-async operations where the function will return immediately and without making any additional requests to the service.
94 95 96 97 98 99 100 101 102 |
# File 'lib/redfish_client/resource.rb', line 94 def wait(response, retries: 10, delay: 1) retries.times do |_i| return response if response.done? sleep(delay) response = get(path: response.monitor) end raise Timeout, "Async operation did not terminate in allotted time" end |