class RedfishClient::Resource
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.
Attributes
Headers, returned from the service when resource has been constructed.
@return [Hash] resource headers
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.
@return [Hash] resource raw data
Public Class Methods
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.
@param connector [RedfishClient::Connector] connector that will be used
to fetch the resources
@param oid [String] OpenData id of the resource @param raw [Hash] raw content to populate resource with @raise [NoResource] resource cannot be retrieved from the service
# File lib/redfish_client/resource.rb, line 56 def initialize(connector, oid: nil, raw: nil) @connector = connector if oid initialize_from_service(oid) else @raw = raw end end
Public Instance Methods
Access resource content.
This function offers a way of accessing resource data in the same way that hash exposes its content.
@param attr [String] key for accessing data @return associated value or `nil` if attr is missing
# File lib/redfish_client/resource.rb, line 93 def [](attr) build_resource(raw[attr]) end
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.
@return [RedfishClient::Response] response @raise [NoODataId] resource has no OpenData id
# File lib/redfish_client/resource.rb, line 223 def delete(field: "@odata.id", path: nil, payload: nil) request(:delete, field, path, payload) end
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 && res[“b”] && res[“b”]`. @params keys [Array<Symbol, String>] sequence of keys to access @return associated value or `nil` if any key is missing
# File lib/redfish_client/resource.rb, line 106 def dig(*keys) keys.reduce(self) { |a, k| a.nil? ? nil : a[k] } end
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.
@param field [String, Symbol] path lookup field @param path [String] path to post to @return [RedfishClient::Response] response @raise [NoODataId] resource has no OpenData id
# File lib/redfish_client/resource.rb, line 173 def get(field: "@odata.id", path: nil) request(:get, field, path) end
Test if resource contains required key.
@param name [String, Symbol] key name to test @return [Boolean] inclusion test result
# File lib/redfish_client/resource.rb, line 114 def key?(name) raw.key?(name.to_s) end
Convenience access for resource data.
Calling `resource.Value` is exactly the same as `resource`.
# File lib/redfish_client/resource.rb, line 121 def method_missing(symbol, *_args, &_block) self[symbol.to_s] end
Issue a PATCH requests to the selected endpoint.
Works exactly the same as the {post} method, but issued a PATCH request to the server.
@param field [String, Symbol] path lookup field @param path [String] path to patch @param payload [Hash<String, >] data to send @return [RedfishClient::Response] response @raise [NoODataId] resource has no OpenData id
# File lib/redfish_client/resource.rb, line 211 def patch(field: "@odata.id", path: nil, payload: nil) request(:patch, field, path, payload) end
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.
@param field [String, Symbol] path lookup field @param path [String] path to post to @param payload [Hash<String, >] data to send @return [RedfishClient::Response] response @raise [NoODataId] resource has no OpenData id
# File lib/redfish_client/resource.rb, line 197 def post(field: "@odata.id", path: nil, payload: nil) request(:post, field, path, payload) end
Refresh resource content from the API
Caling this method will ensure that the resource data is in sync with the Redfis API, invalidating any caches as necessary.
# File lib/redfish_client/resource.rb, line 231 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
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.
@param method [Symbol] HTTP method (:get, :post, :patch or :delete) @param field [String, Symbol] path lookup field @param path [String] path to post to @return [RedfishClient::Response] response @raise [NoODataId] resource has no OpenData id
# File lib/redfish_client/resource.rb, line 153 def request(method, field, path, payload = nil) @connector.request(method, get_path(field, path), payload) end
# File lib/redfish_client/resource.rb, line 125 def respond_to_missing?(symbol, include_private = false) key?(symbol.to_s) || super end
Pretty-print the wrapped content.
@return [String] JSON-serialized raw data
# File lib/redfish_client/resource.rb, line 132 def to_s JSON.pretty_generate(raw) end
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.
@param response [RedfishClient::Response] response @param retries [Integer] number of retries @param delay [Integer] number of seconds between retries @return [RedfishClient::Response] final response @raise [Timeout] if the operation did not terminate in time
# File lib/redfish_client/resource.rb, line 76 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
Private Instance Methods
# File lib/redfish_client/resource.rb, line 279 def build_hash_resource(data) if data.key?("@odata.id") Resource.new(@connector, oid: data["@odata.id"]) else Resource.new(@connector, raw: data) end rescue NoResource nil end
# File lib/redfish_client/resource.rb, line 269 def build_resource(data) return nil if data.nil? case data when Hash then build_hash_resource(data) when Array then data.collect { |d| build_resource(d) } else data end end
# File lib/redfish_client/resource.rb, line 252 def get_fragment(data, fragment) # data, /my/0/part -> data["my"][0]["part"] parse_fragment_string(fragment).reduce(data) do |acc, c| acc[acc.is_a?(Array) ? c.to_i : c] end end
# File lib/redfish_client/resource.rb, line 264 def get_path(field, path) raise NoODataId if path.nil? && !key?(field) path || raw[field] end
# File lib/redfish_client/resource.rb, line 242 def initialize_from_service(oid) url, fragment = oid.split("#", 2) resp = wait(get(path: url)) raise NoResource unless [200, 201].include?(resp.status) @raw = get_fragment(JSON.parse(resp.body), fragment) @raw["@odata.id"] = oid @headers = resp.headers end
# File lib/redfish_client/resource.rb, line 259 def parse_fragment_string(fragment) # /my/0/part -> ["my", "0", "part"] fragment ? fragment.split("/").reject { |i| i == "" } : [] end