redfish_client 0.5.4 → 0.6.1
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.
Potentially problematic release.
This version of redfish_client might be problematic. Click here for more details.
- checksums.yaml +4 -4
- metadata +16 -31
- data/.codeclimate.yml +0 -4
- data/.github/workflows/ci.yml +0 -21
- data/.gitignore +0 -11
- data/.rspec +0 -3
- data/.rubocop.yml +0 -48
- data/.simplecov +0 -3
- data/.yardopts +0 -3
- data/Gemfile +0 -6
- data/README.md +0 -98
- data/Rakefile +0 -6
- data/bin/console +0 -10
- data/bin/setup +0 -8
- data/lib/redfish_client/connector.rb +0 -260
- data/lib/redfish_client/event_listener.rb +0 -35
- data/lib/redfish_client/nil_hash.rb +0 -44
- data/lib/redfish_client/resource.rb +0 -290
- data/lib/redfish_client/response.rb +0 -43
- data/lib/redfish_client/root.rb +0 -77
- data/lib/redfish_client/version.rb +0 -5
- data/lib/redfish_client.rb +0 -20
- data/redfish_client.gemspec +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8af3d1554bfb0aaef0e0c39a93dcff0a651bc4c5c46f10e554bc2d532bc21ad2
|
4
|
+
data.tar.gz: f33ec3d32eb011c22d74e7ac54c24c6bfd4d252a1706e31d46e4acc20a799d72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9843e66d9cdab43dac189edc0106e31f4e41155b3ec7de7fcbaecd164ce39776f989e0370f8e58a2d5d3de832c9ee9231b8cd7c35a759afff71fd5dc6e0cf1b1
|
7
|
+
data.tar.gz: 7dd3ab463ae71d36f0d422ec898a6cfb54a5e818b5a42b36d3888e1c5c4e84e8cebd260d9ec46296b412501467a918f53c3f49b6ef3162967f80317a617c0be2
|
metadata
CHANGED
@@ -1,29 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redfish_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tadej Borovšak
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-02-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: excon
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0.71'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '2'
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
|
-
- - "
|
27
|
+
- - ">="
|
25
28
|
- !ruby/object:Gem::Version
|
26
29
|
version: '0.71'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2'
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: server_sent_events
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,40 +142,19 @@ dependencies:
|
|
136
142
|
- - ">="
|
137
143
|
- !ruby/object:Gem::Version
|
138
144
|
version: '0'
|
139
|
-
description:
|
145
|
+
description:
|
140
146
|
email:
|
141
147
|
- tadej.borovsak@xlab.si
|
142
148
|
executables: []
|
143
149
|
extensions: []
|
144
150
|
extra_rdoc_files: []
|
145
|
-
files:
|
146
|
-
- ".codeclimate.yml"
|
147
|
-
- ".github/workflows/ci.yml"
|
148
|
-
- ".gitignore"
|
149
|
-
- ".rspec"
|
150
|
-
- ".rubocop.yml"
|
151
|
-
- ".simplecov"
|
152
|
-
- ".yardopts"
|
153
|
-
- Gemfile
|
154
|
-
- README.md
|
155
|
-
- Rakefile
|
156
|
-
- bin/console
|
157
|
-
- bin/setup
|
158
|
-
- lib/redfish_client.rb
|
159
|
-
- lib/redfish_client/connector.rb
|
160
|
-
- lib/redfish_client/event_listener.rb
|
161
|
-
- lib/redfish_client/nil_hash.rb
|
162
|
-
- lib/redfish_client/resource.rb
|
163
|
-
- lib/redfish_client/response.rb
|
164
|
-
- lib/redfish_client/root.rb
|
165
|
-
- lib/redfish_client/version.rb
|
166
|
-
- redfish_client.gemspec
|
151
|
+
files: []
|
167
152
|
homepage: https://github.com/xlab-steampunk/redfish-client-ruby
|
168
153
|
licenses:
|
169
154
|
- Apache-2.0
|
170
155
|
metadata:
|
171
156
|
allowed_push_host: https://rubygems.org
|
172
|
-
post_install_message:
|
157
|
+
post_install_message:
|
173
158
|
rdoc_options: []
|
174
159
|
require_paths:
|
175
160
|
- lib
|
@@ -184,8 +169,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
184
169
|
- !ruby/object:Gem::Version
|
185
170
|
version: '0'
|
186
171
|
requirements: []
|
187
|
-
rubygems_version: 3.
|
188
|
-
signing_key:
|
172
|
+
rubygems_version: 3.1.6
|
173
|
+
signing_key:
|
189
174
|
specification_version: 4
|
190
175
|
summary: Simple Redfish client library
|
191
176
|
test_files: []
|
data/.codeclimate.yml
DELETED
data/.github/workflows/ci.yml
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
name: Ruby
|
2
|
-
|
3
|
-
on:
|
4
|
-
push:
|
5
|
-
branches: [ master ]
|
6
|
-
pull_request:
|
7
|
-
|
8
|
-
jobs:
|
9
|
-
test:
|
10
|
-
runs-on: ubuntu-latest
|
11
|
-
steps:
|
12
|
-
- name: Clone repo
|
13
|
-
uses: actions/checkout@v2
|
14
|
-
- name: Set up Ruby
|
15
|
-
uses: ruby/setup-ruby@v1
|
16
|
-
with:
|
17
|
-
ruby-version: 2.6
|
18
|
-
- name: Install dependencies
|
19
|
-
run: bundle install
|
20
|
-
- name: Run tests
|
21
|
-
run: bundle exec rake
|
data/.gitignore
DELETED
data/.rspec
DELETED
data/.rubocop.yml
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
AllCops:
|
2
|
-
TargetRubyVersion: 2.3
|
3
|
-
Exclude:
|
4
|
-
- redfish_client.gemspec
|
5
|
-
- Gemfile
|
6
|
-
- Rakefile
|
7
|
-
- bin/**
|
8
|
-
|
9
|
-
Layout/MultilineOperationIndentation:
|
10
|
-
EnforcedStyle: indented
|
11
|
-
|
12
|
-
Layout/MultilineMethodCallIndentation:
|
13
|
-
EnforcedStyle: indented
|
14
|
-
|
15
|
-
Style/MethodMissing:
|
16
|
-
Exclude:
|
17
|
-
- lib/redfish_client/resource.rb
|
18
|
-
|
19
|
-
Style/StringLiterals:
|
20
|
-
EnforcedStyle: double_quotes
|
21
|
-
|
22
|
-
Style/Documentation:
|
23
|
-
Enabled: false
|
24
|
-
|
25
|
-
Style/BracesAroundHashParameters:
|
26
|
-
EnforcedStyle: context_dependent
|
27
|
-
|
28
|
-
Style/TrailingCommaInArguments:
|
29
|
-
EnforcedStyleForMultiline: comma
|
30
|
-
|
31
|
-
Style/TrailingCommaInArrayLiteral:
|
32
|
-
EnforcedStyleForMultiline: comma
|
33
|
-
|
34
|
-
Style/TrailingCommaInHashLiteral:
|
35
|
-
EnforcedStyleForMultiline: comma
|
36
|
-
|
37
|
-
Metrics/AbcSize:
|
38
|
-
Max: 20
|
39
|
-
|
40
|
-
Metrics/BlockLength:
|
41
|
-
Exclude:
|
42
|
-
- spec/**/*.rb
|
43
|
-
|
44
|
-
Metrics/ClassLength:
|
45
|
-
Max: 500
|
46
|
-
|
47
|
-
Metrics/ParameterLists:
|
48
|
-
CountKeywordArgs: false
|
data/.simplecov
DELETED
data/.yardopts
DELETED
data/Gemfile
DELETED
data/README.md
DELETED
@@ -1,98 +0,0 @@
|
|
1
|
-
# Redfish Ruby Client
|
2
|
-
|
3
|
-
[](https://travis-ci.org/xlab-si/redfish-client-ruby)
|
4
|
-
[](https://codeclimate.com/github/xlab-si/redfish-client-ruby/maintainability)
|
5
|
-
[](https://codeclimate.com/github/xlab-si/redfish-client-ruby/test_coverage)
|
6
|
-
[](https://beta.gemnasium.com/projects/github.com/xlab-si/redfish_client)
|
7
|
-
[](https://hakiri.io/github/xlab-si/redfish_client/master)
|
8
|
-
|
9
|
-
|
10
|
-
This repository contains source code for redfish_client gem that can be used
|
11
|
-
to connect to Redfish services.
|
12
|
-
|
13
|
-
|
14
|
-
## Installation
|
15
|
-
|
16
|
-
Add this line to your application's Gemfile:
|
17
|
-
|
18
|
-
gem "redfish_client"
|
19
|
-
|
20
|
-
And then execute:
|
21
|
-
|
22
|
-
$ bundle
|
23
|
-
|
24
|
-
Or install it yourself as:
|
25
|
-
|
26
|
-
$ gem install redfish_client
|
27
|
-
|
28
|
-
|
29
|
-
## Usage
|
30
|
-
|
31
|
-
Minimal program that uses this gem would look something like this:
|
32
|
-
|
33
|
-
require "redfish_client"
|
34
|
-
|
35
|
-
root = RedfishClient.new("https://localhost:8000",
|
36
|
-
prefix: "/redfish/v1",
|
37
|
-
verify: false)
|
38
|
-
puts root
|
39
|
-
root.login("username", "password")
|
40
|
-
puts root.Systems
|
41
|
-
root.logout
|
42
|
-
|
43
|
-
|
44
|
-
## Handling asynchronous operations
|
45
|
-
|
46
|
-
Redfish service can return a 202 status when we request an execution of a
|
47
|
-
long-running operation (e.g. updating firmware). We are expected to poll the
|
48
|
-
monitor for changes until the job terminates.
|
49
|
-
|
50
|
-
Responses in Redfish client have a built-in support for this, so polling the
|
51
|
-
service is rather painless:
|
52
|
-
|
53
|
-
# Start the async action
|
54
|
-
response = update_service.Actions["#UpdateService.SimpleUpdate"].post(
|
55
|
-
field: "target", payload: { ... },
|
56
|
-
)
|
57
|
-
# Wait for the termination
|
58
|
-
response = update_service.wait(response)
|
59
|
-
# Do something with response
|
60
|
-
|
61
|
-
It is also possible to manually poll the response like this:
|
62
|
-
|
63
|
-
response = update_service.Actions["#UpdateService.SimpleUpdate"].post(
|
64
|
-
field: "target", payload: { ... },
|
65
|
-
)
|
66
|
-
until response.done?
|
67
|
-
# wait a bit
|
68
|
-
response = update_service.get(response.monitor)
|
69
|
-
end
|
70
|
-
|
71
|
-
Response is also safe to (de)serialize, which means that the process that
|
72
|
-
started the async operation and the process that will wait for it can be
|
73
|
-
separate:
|
74
|
-
|
75
|
-
response = update_service.Actions["#UpdateService.SimpleUpdate"].post(
|
76
|
-
field: "target", payload: { ... },
|
77
|
-
)
|
78
|
-
send_response_somewhere(response.to_h)
|
79
|
-
|
80
|
-
# Somewhere else
|
81
|
-
response = Response.from_hash(receive_response_from_somewhere)
|
82
|
-
|
83
|
-
|
84
|
-
## Development
|
85
|
-
|
86
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then,
|
87
|
-
run `bundle exec rake spec` to run the tests. You can also run `bin/console`
|
88
|
-
for an interactive prompt that will allow you to experiment.
|
89
|
-
|
90
|
-
To create new release, increment the version number, commit the change, tag
|
91
|
-
the commit and push tag to the GitHub. Travis CI will pick from there on and
|
92
|
-
create new release, publishing it on https://rubygems.org.
|
93
|
-
|
94
|
-
|
95
|
-
## Contributing
|
96
|
-
|
97
|
-
Bug reports and pull requests are welcome on GitHub at
|
98
|
-
https://github.com/xlab-si/redfish_client.
|
data/Rakefile
DELETED
data/bin/console
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
require "redfish_client"
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
require "pry"
|
10
|
-
Pry.start
|
data/bin/setup
DELETED
@@ -1,260 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "base64"
|
4
|
-
require "excon"
|
5
|
-
require "json"
|
6
|
-
|
7
|
-
require "redfish_client/nil_hash"
|
8
|
-
require "redfish_client/response"
|
9
|
-
|
10
|
-
module RedfishClient
|
11
|
-
# Connector serves as a low-level wrapper around HTTP calls that are used
|
12
|
-
# to retrieve data from the service API. It abstracts away implementation
|
13
|
-
# details such as sending the proper headers in request, which do not
|
14
|
-
# change between resource fetches.
|
15
|
-
#
|
16
|
-
# Library users should treat this class as an implementation detail and
|
17
|
-
# use higer-level {RedfishClient::Resource} instead.
|
18
|
-
class Connector
|
19
|
-
# AuthError is raised if the credentials are invalid.
|
20
|
-
class AuthError < StandardError; end
|
21
|
-
|
22
|
-
# Default headers, as required by Redfish spec
|
23
|
-
# https://redfish.dmtf.org/schemas/DSP0266_1.4.0.html#request-headers
|
24
|
-
DEFAULT_HEADERS = {
|
25
|
-
"Accept" => "application/json",
|
26
|
-
"OData-Version" => "4.0",
|
27
|
-
}.freeze
|
28
|
-
|
29
|
-
# Basic and token authentication header names
|
30
|
-
BASIC_AUTH_HEADER = "Authorization"
|
31
|
-
TOKEN_AUTH_HEADER = "X-Auth-Token"
|
32
|
-
LOCATION_HEADER = "Location"
|
33
|
-
|
34
|
-
# Create new connector.
|
35
|
-
#
|
36
|
-
# By default, connector performs no caching. If caching is desired,
|
37
|
-
# Hash should be used as a cache implementation.
|
38
|
-
#
|
39
|
-
# It is also possible to pass in custom caching class. Instances of that
|
40
|
-
# class should respond to the following four methods:
|
41
|
-
#
|
42
|
-
# 1. `[](key)` - Used to access cached content and should return
|
43
|
-
# `nil` if the key has no associated value.
|
44
|
-
# 2. `[]=(key, value)` - Cache `value` under the `key`
|
45
|
-
# 3. `clear` - Clear the complete cache.
|
46
|
-
# 4. `delete(key)` - Invalidate cache entry associated with `key`.
|
47
|
-
#
|
48
|
-
# @param url [String] base url of the Redfish service
|
49
|
-
# @param verify [Boolean] verify SSL certificate of the service
|
50
|
-
# @param cache [Object] cache backend
|
51
|
-
def initialize(url, verify: true, cache: nil)
|
52
|
-
@url = url
|
53
|
-
@headers = DEFAULT_HEADERS.dup
|
54
|
-
middlewares = Excon.defaults[:middlewares] +
|
55
|
-
[Excon::Middleware::RedirectFollower]
|
56
|
-
@connection = Excon.new(@url,
|
57
|
-
ssl_verify_peer: verify,
|
58
|
-
middlewares: middlewares)
|
59
|
-
@cache = cache || NilHash.new
|
60
|
-
end
|
61
|
-
|
62
|
-
# Add HTTP headers to the requests made by the connector.
|
63
|
-
#
|
64
|
-
# @param headers [Hash<String, String>] headers to be added
|
65
|
-
def add_headers(headers)
|
66
|
-
@headers.merge!(headers)
|
67
|
-
end
|
68
|
-
|
69
|
-
# Remove HTTP headers from requests made by the connector.
|
70
|
-
#
|
71
|
-
# Headers that are not currently set are silently ignored and no error is
|
72
|
-
# raised.
|
73
|
-
#
|
74
|
-
# @param headers [List<String>] headers to remove
|
75
|
-
def remove_headers(headers)
|
76
|
-
headers.each { |h| @headers.delete(h) }
|
77
|
-
end
|
78
|
-
|
79
|
-
# Issue requests to the service.
|
80
|
-
#
|
81
|
-
# @param mathod [Symbol] HTTP method (:get, :post, :patch or :delete)
|
82
|
-
# @param path [String] path to the resource, relative to the base
|
83
|
-
# @param data [Hash] data to be sent over the socket
|
84
|
-
# @return [Response] response object
|
85
|
-
def request(method, path, data = nil)
|
86
|
-
return @cache[path] if method == :get && @cache[path]
|
87
|
-
|
88
|
-
do_request(method, path, data).tap do |r|
|
89
|
-
@cache[path] = r if method == :get && r.status == 200
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
# Issue GET request to service.
|
94
|
-
#
|
95
|
-
# This method will first try to return cached response if available. If
|
96
|
-
# cache does not contain entry for this request, data will be fetched from
|
97
|
-
# remote and then cached, but only if the response has an OK (200) status.
|
98
|
-
#
|
99
|
-
# @param path [String] path to the resource, relative to the base url
|
100
|
-
# @return [Response] response object
|
101
|
-
def get(path)
|
102
|
-
request(:get, path)
|
103
|
-
end
|
104
|
-
|
105
|
-
# Issue POST requests to the service.
|
106
|
-
#
|
107
|
-
# @param path [String] path to the resource, relative to the base
|
108
|
-
# @param data [Hash] data to be sent over the socket, JSON encoded
|
109
|
-
# @return [Response] response object
|
110
|
-
def post(path, data = nil)
|
111
|
-
request(:post, path, data)
|
112
|
-
end
|
113
|
-
|
114
|
-
# Issue PATCH requests to the service.
|
115
|
-
#
|
116
|
-
# @param path [String] path to the resource, relative to the base
|
117
|
-
# @param data [Hash] data to be sent over the socket
|
118
|
-
# @return [Response] response object
|
119
|
-
def patch(path, data = nil)
|
120
|
-
request(:patch, path, data)
|
121
|
-
end
|
122
|
-
|
123
|
-
# Issue DELETE requests to the service.
|
124
|
-
#
|
125
|
-
# @param path [String] path to the resource, relative to the base
|
126
|
-
# @return [Response] response object
|
127
|
-
def delete(path)
|
128
|
-
request(:delete, path)
|
129
|
-
end
|
130
|
-
|
131
|
-
# Clear the cached responses.
|
132
|
-
#
|
133
|
-
# If path is passed as a parameter, only one cache entry gets invalidated,
|
134
|
-
# else complete cache gets invalidated.
|
135
|
-
#
|
136
|
-
# Next GET request will repopulate the cache.
|
137
|
-
#
|
138
|
-
# @param path [String] path to invalidate
|
139
|
-
def reset(path = nil)
|
140
|
-
path.nil? ? @cache.clear : @cache.delete(path)
|
141
|
-
end
|
142
|
-
|
143
|
-
# Set authentication-related variables.
|
144
|
-
#
|
145
|
-
# Last parameter controls the kind of login connector will perform. If
|
146
|
-
# session_path is `nil`, basic authentication will be used, otherwise
|
147
|
-
# connector will use session-based authentication.
|
148
|
-
#
|
149
|
-
# Note that actual login is done lazily. If you need to check for
|
150
|
-
# credential validity, call #{login} method.
|
151
|
-
#
|
152
|
-
# @param username [String] API username
|
153
|
-
# @param password [String] API password
|
154
|
-
# @param auth_test_path [String] API path to test credential's validity
|
155
|
-
# @param session_path [String, nil] API session path
|
156
|
-
def set_auth_info(username, password, auth_test_path, session_path = nil)
|
157
|
-
@username = username
|
158
|
-
@password = password
|
159
|
-
@auth_test_path = auth_test_path
|
160
|
-
@session_path = session_path
|
161
|
-
end
|
162
|
-
|
163
|
-
# Authenticate against the service.
|
164
|
-
#
|
165
|
-
# Calling this method will try to authenticate against API using
|
166
|
-
# credentials provided by #{set_auth_info} call.
|
167
|
-
# If authentication fails, # {AuthError} will be raised.
|
168
|
-
#
|
169
|
-
# @raise [AuthError] if credentials are invalid
|
170
|
-
def login
|
171
|
-
@session_path ? session_login : basic_login
|
172
|
-
end
|
173
|
-
|
174
|
-
# Sign out of the service.
|
175
|
-
def logout
|
176
|
-
# We bypass request here because we do not want any retries on 401
|
177
|
-
# when doing logout.
|
178
|
-
if @session_oid
|
179
|
-
params = prepare_request_params(:delete, @session_oid)
|
180
|
-
@connection.request(params)
|
181
|
-
@session_oid = nil
|
182
|
-
end
|
183
|
-
remove_headers([BASIC_AUTH_HEADER, TOKEN_AUTH_HEADER])
|
184
|
-
end
|
185
|
-
|
186
|
-
private
|
187
|
-
|
188
|
-
def do_request(method, path, data)
|
189
|
-
params = prepare_request_params(method, path, data)
|
190
|
-
r = @connection.request(params)
|
191
|
-
if r.status == 401
|
192
|
-
login
|
193
|
-
r = @connection.request(params)
|
194
|
-
end
|
195
|
-
Response.new(r.status, downcase_headers(r.data[:headers]), r.data[:body])
|
196
|
-
end
|
197
|
-
|
198
|
-
def downcase_headers(headers)
|
199
|
-
headers.each_with_object({}) { |(k, v), obj| obj[k.downcase] = v }
|
200
|
-
end
|
201
|
-
|
202
|
-
def prepare_request_params(method, path, data = nil)
|
203
|
-
params = { method: method, path: path }
|
204
|
-
if data
|
205
|
-
params[:body] = data.to_json
|
206
|
-
params[:headers] = @headers.merge("Content-Type" => "application/json")
|
207
|
-
else
|
208
|
-
params[:headers] = @headers
|
209
|
-
end
|
210
|
-
params
|
211
|
-
end
|
212
|
-
|
213
|
-
def session_login
|
214
|
-
# We bypass request here because we do not want any retries on 401
|
215
|
-
# when doing login.
|
216
|
-
params = prepare_request_params(:post, @session_path,
|
217
|
-
"UserName" => @username,
|
218
|
-
"Password" => @password)
|
219
|
-
r = @connection.request(params)
|
220
|
-
raise_invalid_auth_error unless r.status == 201
|
221
|
-
|
222
|
-
body = JSON.parse(r.data[:body])
|
223
|
-
headers = r.data[:headers]
|
224
|
-
|
225
|
-
add_headers(TOKEN_AUTH_HEADER => headers[TOKEN_AUTH_HEADER])
|
226
|
-
save_session_oid!(body, headers)
|
227
|
-
end
|
228
|
-
|
229
|
-
def save_session_oid!(body, headers)
|
230
|
-
@session_oid = body["@odata.id"] if body.key?("@odata.id")
|
231
|
-
return if @session_oid
|
232
|
-
|
233
|
-
return unless headers.key?(LOCATION_HEADER)
|
234
|
-
|
235
|
-
location = URI.parse(headers[LOCATION_HEADER])
|
236
|
-
@session_oid = [location.path, location.query].compact.join("?")
|
237
|
-
end
|
238
|
-
|
239
|
-
def basic_login
|
240
|
-
payload = Base64.encode64("#{@username}:#{@password}").strip
|
241
|
-
add_headers(BASIC_AUTH_HEADER => "Basic #{payload}")
|
242
|
-
return if auth_valid?
|
243
|
-
|
244
|
-
remove_headers([BASIC_AUTH_HEADER])
|
245
|
-
raise_invalid_auth_error
|
246
|
-
end
|
247
|
-
|
248
|
-
def raise_invalid_auth_error
|
249
|
-
raise AuthError, "Invalid credentials"
|
250
|
-
end
|
251
|
-
|
252
|
-
def auth_valid?
|
253
|
-
# We bypass request here because we do not want any retries on 401
|
254
|
-
# when checking authentication headers.
|
255
|
-
reset(@auth_test_path) # Do not want to see cached response
|
256
|
-
params = prepare_request_params(:get, @auth_test_path)
|
257
|
-
@connection.request(params).status == 200
|
258
|
-
end
|
259
|
-
end
|
260
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "json"
|
4
|
-
require "uri"
|
5
|
-
|
6
|
-
module RedfishClient
|
7
|
-
# EventListener class can be used to stream events from Redfish service. It
|
8
|
-
# is a thin wrapper around SSE listener that does the dirty work of
|
9
|
-
# splitting each event into its EventRecords and reporting them as separate
|
10
|
-
# events.
|
11
|
-
class EventListener
|
12
|
-
# Create new EventListener instance.
|
13
|
-
#
|
14
|
-
# @param sse_client [ServerSentEvents::Client] SSE client
|
15
|
-
def initialize(sse_client)
|
16
|
-
@sse_client = sse_client
|
17
|
-
end
|
18
|
-
|
19
|
-
# Stream events from redfish service.
|
20
|
-
#
|
21
|
-
# Events that this method yields are actually EventRecords, extracted from
|
22
|
-
# the actual Redfish Event.
|
23
|
-
def listen
|
24
|
-
@sse_client.listen do |event|
|
25
|
-
split_event_into_records(event).each { |r| yield(r) }
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def split_event_into_records(event)
|
32
|
-
JSON.parse(event.data).fetch("Events", [])
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RedfishClient
|
4
|
-
# NilHash imitates the built-in Hash class without storing anything
|
5
|
-
# permanently.
|
6
|
-
#
|
7
|
-
# Main use of this class is as a non-caching connector backend.
|
8
|
-
class NilHash
|
9
|
-
# Access hash member.
|
10
|
-
#
|
11
|
-
# Since this implementation does not store any data, return value is
|
12
|
-
# always nil.
|
13
|
-
#
|
14
|
-
# @param _key not used
|
15
|
-
# @return [nil]
|
16
|
-
def [](_key)
|
17
|
-
nil
|
18
|
-
end
|
19
|
-
|
20
|
-
# Set hash member.
|
21
|
-
#
|
22
|
-
# This is just a pass-through method, since it always simply returns the
|
23
|
-
# value without actually storing it.
|
24
|
-
#
|
25
|
-
# @param _key not used
|
26
|
-
# @param value [Object] any value
|
27
|
-
# @return [Object] value
|
28
|
-
def []=(_key, value)
|
29
|
-
value
|
30
|
-
end
|
31
|
-
|
32
|
-
# Clear the contents of the cache.
|
33
|
-
#
|
34
|
-
# Since hash is not storing anything, this is a no-op.
|
35
|
-
def clear; end
|
36
|
-
|
37
|
-
# Delete entry from hash.
|
38
|
-
#
|
39
|
-
# Since hash is not storing anything, this is a no-op.
|
40
|
-
#
|
41
|
-
# @param _key not used
|
42
|
-
def delete(_key) end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,290 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "json"
|
4
|
-
|
5
|
-
module RedfishClient
|
6
|
-
# Resource is basic building block of Redfish client and serves as a
|
7
|
-
# container for the data that is retrieved from the Redfish service.
|
8
|
-
#
|
9
|
-
# When we interact with the Redfish service, resource will wrap the data
|
10
|
-
# retrieved from the service API and offer us dot-notation accessors for
|
11
|
-
# values stored.
|
12
|
-
#
|
13
|
-
# Resource will also load any sub-resource on demand when we access it.
|
14
|
-
# For example, if we have a root Redfish resource stored in `root`,
|
15
|
-
# accessing `root.SessionService` will automatically fetch the appropriate
|
16
|
-
# resource from the API.
|
17
|
-
#
|
18
|
-
# In order to reduce the amount of requests being sent to the service,
|
19
|
-
# resource can also utilise caching connector. If we would like to get
|
20
|
-
# fresh values from the service, {#refresh} call will flush the cache and
|
21
|
-
# retrieve fresh data from the remote.
|
22
|
-
class Resource
|
23
|
-
# NoODataId error is raised when operation would need OpenData id of the
|
24
|
-
# resource to accomplish the task a hand.
|
25
|
-
class NoODataId < StandardError; end
|
26
|
-
|
27
|
-
# NoResource error is raised if the service cannot find requested
|
28
|
-
# resource.
|
29
|
-
class NoResource < StandardError; end
|
30
|
-
|
31
|
-
# Timeout error is raised if the async request is not handled in due time.
|
32
|
-
class Timeout < StandardError; end
|
33
|
-
|
34
|
-
# Headers, returned from the service when resource has been constructed.
|
35
|
-
#
|
36
|
-
# @return [Hash] resource headers
|
37
|
-
attr_reader :headers
|
38
|
-
|
39
|
-
# Raw data that has been used to construct resource by either fetching it
|
40
|
-
# from the remote API or by being passed-in as a parameter to constructor.
|
41
|
-
#
|
42
|
-
# @return [Hash] resource raw data
|
43
|
-
attr_reader :raw
|
44
|
-
|
45
|
-
# Create new resource.
|
46
|
-
#
|
47
|
-
# Resource can be created either by passing in OpenData identifier or
|
48
|
-
# supplying the content (hash). In the first case, connector will be used
|
49
|
-
# to fetch the resource data. In the second case, resource only wraps the
|
50
|
-
# passed-in hash and does no fetching.
|
51
|
-
#
|
52
|
-
# @param connector [RedfishClient::Connector] connector that will be used
|
53
|
-
# to fetch the resources
|
54
|
-
# @param oid [String] OpenData id of the resource
|
55
|
-
# @param raw [Hash] raw content to populate resource with
|
56
|
-
# @raise [NoResource] resource cannot be retrieved from the service
|
57
|
-
def initialize(connector, oid: nil, raw: nil)
|
58
|
-
@connector = connector
|
59
|
-
if oid
|
60
|
-
initialize_from_service(oid)
|
61
|
-
else
|
62
|
-
@raw = raw
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
# Wait for the potentially async operation to terminate
|
67
|
-
#
|
68
|
-
# Note that this can be safely called on response from non-async
|
69
|
-
# operations where the function will return immediately and without making
|
70
|
-
# any additional requests to the service.
|
71
|
-
#
|
72
|
-
# @param response [RedfishClient::Response] response
|
73
|
-
# @param retries [Integer] number of retries
|
74
|
-
# @param delay [Integer] number of seconds between retries
|
75
|
-
# @return [RedfishClient::Response] final response
|
76
|
-
# @raise [Timeout] if the operation did not terminate in time
|
77
|
-
def wait(response, retries: 10, delay: 1)
|
78
|
-
retries.times do |_i|
|
79
|
-
return response if response.done?
|
80
|
-
|
81
|
-
sleep(delay)
|
82
|
-
response = get(path: response.monitor)
|
83
|
-
end
|
84
|
-
raise Timeout, "Async operation did not terminate in allotted time"
|
85
|
-
end
|
86
|
-
|
87
|
-
# Access resource content.
|
88
|
-
#
|
89
|
-
# This function offers a way of accessing resource data in the same way
|
90
|
-
# that hash exposes its content.
|
91
|
-
#
|
92
|
-
# @param attr [String] key for accessing data
|
93
|
-
# @return associated value or `nil` if attr is missing
|
94
|
-
def [](attr)
|
95
|
-
build_resource(raw[attr])
|
96
|
-
end
|
97
|
-
|
98
|
-
# Safely access nested resource content.
|
99
|
-
#
|
100
|
-
# This function is an equivalent of safe navigation operator that can be
|
101
|
-
# used with arbitrary keys.
|
102
|
-
#
|
103
|
-
# Calling `res.dig("a", "b", "c")` is equivalent to `res.a&.b&.c` and
|
104
|
-
# `res["a"] && res["a"]["b"] && res["a"]["b"]["c"]`.
|
105
|
-
# @params keys [Array<Symbol, String>] sequence of keys to access
|
106
|
-
# @return associated value or `nil` if any key is missing
|
107
|
-
def dig(*keys)
|
108
|
-
keys.reduce(self) { |a, k| a.nil? ? nil : a[k] }
|
109
|
-
end
|
110
|
-
|
111
|
-
# Test if resource contains required key.
|
112
|
-
#
|
113
|
-
# @param name [String, Symbol] key name to test
|
114
|
-
# @return [Boolean] inclusion test result
|
115
|
-
def key?(name)
|
116
|
-
raw.key?(name.to_s)
|
117
|
-
end
|
118
|
-
|
119
|
-
# Convenience access for resource data.
|
120
|
-
#
|
121
|
-
# Calling `resource.Value` is exactly the same as `resource["Value"]`.
|
122
|
-
def method_missing(symbol, *_args, &_block)
|
123
|
-
self[symbol.to_s]
|
124
|
-
end
|
125
|
-
|
126
|
-
def respond_to_missing?(symbol, include_private = false)
|
127
|
-
key?(symbol.to_s) || super
|
128
|
-
end
|
129
|
-
|
130
|
-
# Pretty-print the wrapped content.
|
131
|
-
#
|
132
|
-
# @return [String] JSON-serialized raw data
|
133
|
-
def to_s
|
134
|
-
JSON.pretty_generate(raw)
|
135
|
-
end
|
136
|
-
|
137
|
-
# Issue a requests to the selected endpoint.
|
138
|
-
#
|
139
|
-
# By default, request will be sent to the path, stored in `@odata.id`
|
140
|
-
# field. Source field can be changed by specifying the `field` parameter
|
141
|
-
# when calling this function. Specifying the `path` argument will bypass
|
142
|
-
# the field lookup altogether and issue a request directly to the selected
|
143
|
-
# path.
|
144
|
-
#
|
145
|
-
# If the resource has no lookup field, {NoODataId} error will be raised,
|
146
|
-
# since posting to non-networked resources makes no sense and probably
|
147
|
-
# indicates bug in library consumer.
|
148
|
-
#
|
149
|
-
# @param method [Symbol] HTTP method (:get, :post, :patch or :delete)
|
150
|
-
# @param field [String, Symbol] path lookup field
|
151
|
-
# @param path [String] path to post to
|
152
|
-
# @return [RedfishClient::Response] response
|
153
|
-
# @raise [NoODataId] resource has no OpenData id
|
154
|
-
def request(method, field, path, payload = nil)
|
155
|
-
@connector.request(method, get_path(field, path), payload)
|
156
|
-
end
|
157
|
-
|
158
|
-
# Issue a GET requests to the selected endpoint.
|
159
|
-
#
|
160
|
-
# By default, GET request will be sent to the path, stored in `@odata.id`
|
161
|
-
# field. Source field can be changed by specifying the `field` parameter
|
162
|
-
# when calling this function. Specifying the `path` argument will bypass
|
163
|
-
# the field lookup altogether and issue a GET request directly to the
|
164
|
-
# selected path.
|
165
|
-
#
|
166
|
-
# If the resource has no lookup field, {NoODataId} error will be raised,
|
167
|
-
# since posting to non-networked resources makes no sense and probably
|
168
|
-
# indicates bug in library consumer.
|
169
|
-
#
|
170
|
-
# @param field [String, Symbol] path lookup field
|
171
|
-
# @param path [String] path to post to
|
172
|
-
# @return [RedfishClient::Response] response
|
173
|
-
# @raise [NoODataId] resource has no OpenData id
|
174
|
-
def get(field: "@odata.id", path: nil)
|
175
|
-
request(:get, field, path)
|
176
|
-
end
|
177
|
-
|
178
|
-
# Issue a POST requests to the selected endpoint.
|
179
|
-
#
|
180
|
-
# By default, POST request will be sent to the path, stored in `@odata.id`
|
181
|
-
# field. Source field can be changed by specifying the `field` parameter
|
182
|
-
# when calling this function. Specifying the `path` argument will bypass
|
183
|
-
# the field lookup altogether and POST directly to the requested path.
|
184
|
-
#
|
185
|
-
# In order to avoid having to manually serialize data to JSON, this
|
186
|
-
# function call takes Hash as a payload and encodes it before sending it
|
187
|
-
# to the endpoint.
|
188
|
-
#
|
189
|
-
# If the resource has no lookup field, {NoODataId} error will be raised,
|
190
|
-
# since posting to non-networked resources makes no sense and probably
|
191
|
-
# indicates bug in library consumer.
|
192
|
-
#
|
193
|
-
# @param field [String, Symbol] path lookup field
|
194
|
-
# @param path [String] path to post to
|
195
|
-
# @param payload [Hash<String, >] data to send
|
196
|
-
# @return [RedfishClient::Response] response
|
197
|
-
# @raise [NoODataId] resource has no OpenData id
|
198
|
-
def post(field: "@odata.id", path: nil, payload: nil)
|
199
|
-
request(:post, field, path, payload)
|
200
|
-
end
|
201
|
-
|
202
|
-
# Issue a PATCH requests to the selected endpoint.
|
203
|
-
#
|
204
|
-
# Works exactly the same as the {post} method, but issued a PATCH request
|
205
|
-
# to the server.
|
206
|
-
#
|
207
|
-
# @param field [String, Symbol] path lookup field
|
208
|
-
# @param path [String] path to patch
|
209
|
-
# @param payload [Hash<String, >] data to send
|
210
|
-
# @return [RedfishClient::Response] response
|
211
|
-
# @raise [NoODataId] resource has no OpenData id
|
212
|
-
def patch(field: "@odata.id", path: nil, payload: nil)
|
213
|
-
request(:patch, field, path, payload)
|
214
|
-
end
|
215
|
-
|
216
|
-
# Issue a DELETE requests to the endpoint of the resource.
|
217
|
-
#
|
218
|
-
# If the resource has no `@odata.id` field, {NoODataId} error will be
|
219
|
-
# raised, since deleting non-networked resources makes no sense and
|
220
|
-
# probably indicates bug in library consumer.
|
221
|
-
#
|
222
|
-
# @return [RedfishClient::Response] response
|
223
|
-
# @raise [NoODataId] resource has no OpenData id
|
224
|
-
def delete(field: "@odata.id", path: nil, payload: nil)
|
225
|
-
request(:delete, field, path, payload)
|
226
|
-
end
|
227
|
-
|
228
|
-
# Refresh resource content from the API
|
229
|
-
#
|
230
|
-
# Caling this method will ensure that the resource data is in sync with
|
231
|
-
# the Redfis API, invalidating any caches as necessary.
|
232
|
-
def refresh
|
233
|
-
return unless self["@odata.id"]
|
234
|
-
|
235
|
-
# TODO(@tadeboro): raise more sensible exception if resource cannot be
|
236
|
-
# refreshed.
|
237
|
-
@connector.reset(self["@odata.id"])
|
238
|
-
initialize_from_service(self["@odata.id"])
|
239
|
-
end
|
240
|
-
|
241
|
-
private
|
242
|
-
|
243
|
-
def initialize_from_service(oid)
|
244
|
-
url, fragment = oid.split("#", 2)
|
245
|
-
resp = wait(get(path: url))
|
246
|
-
raise NoResource unless [200, 201].include?(resp.status)
|
247
|
-
|
248
|
-
@raw = get_fragment(JSON.parse(resp.body), fragment)
|
249
|
-
@raw["@odata.id"] = oid
|
250
|
-
@headers = resp.headers
|
251
|
-
end
|
252
|
-
|
253
|
-
def get_fragment(data, fragment)
|
254
|
-
# data, /my/0/part -> data["my"][0]["part"]
|
255
|
-
parse_fragment_string(fragment).reduce(data) do |acc, c|
|
256
|
-
acc[acc.is_a?(Array) ? c.to_i : c]
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
def parse_fragment_string(fragment)
|
261
|
-
# /my/0/part -> ["my", "0", "part"]
|
262
|
-
fragment ? fragment.split("/").reject { |i| i == "" } : []
|
263
|
-
end
|
264
|
-
|
265
|
-
def get_path(field, path)
|
266
|
-
raise NoODataId if path.nil? && !key?(field)
|
267
|
-
path || raw[field]
|
268
|
-
end
|
269
|
-
|
270
|
-
def build_resource(data)
|
271
|
-
return nil if data.nil?
|
272
|
-
|
273
|
-
case data
|
274
|
-
when Hash then build_hash_resource(data)
|
275
|
-
when Array then data.collect { |d| build_resource(d) }
|
276
|
-
else data
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
def build_hash_resource(data)
|
281
|
-
if data.key?("@odata.id")
|
282
|
-
Resource.new(@connector, oid: data["@odata.id"])
|
283
|
-
else
|
284
|
-
Resource.new(@connector, raw: data)
|
285
|
-
end
|
286
|
-
rescue NoResource
|
287
|
-
nil
|
288
|
-
end
|
289
|
-
end
|
290
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "uri"
|
4
|
-
|
5
|
-
module RedfishClient
|
6
|
-
# Response struct.
|
7
|
-
#
|
8
|
-
# This struct is returned from the methods that interact with the remote API.
|
9
|
-
class Response
|
10
|
-
attr_reader :status
|
11
|
-
attr_reader :headers
|
12
|
-
attr_reader :body
|
13
|
-
|
14
|
-
def initialize(status, headers, body)
|
15
|
-
@status = status
|
16
|
-
@headers = headers
|
17
|
-
@body = body
|
18
|
-
end
|
19
|
-
|
20
|
-
def done?
|
21
|
-
status != 202
|
22
|
-
end
|
23
|
-
|
24
|
-
def monitor
|
25
|
-
return nil if done?
|
26
|
-
|
27
|
-
uri = URI.parse(headers["location"])
|
28
|
-
[uri.path, uri.query].compact.join("?")
|
29
|
-
end
|
30
|
-
|
31
|
-
def to_h
|
32
|
-
{ "status" => status, "headers" => headers, "body" => body }
|
33
|
-
end
|
34
|
-
|
35
|
-
def to_s
|
36
|
-
"Response[status=#{status}, headers=#{headers}, body='#{body}']"
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.from_hash(data)
|
40
|
-
new(*data.values_at("status", "headers", "body"))
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
data/lib/redfish_client/root.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "server_sent_events"
|
4
|
-
|
5
|
-
require "redfish_client/event_listener"
|
6
|
-
require "redfish_client/resource"
|
7
|
-
|
8
|
-
module RedfishClient
|
9
|
-
# Root resource represents toplevel entry point into Redfish service data.
|
10
|
-
# Its main purpose is to provide authentication support for the API.
|
11
|
-
class Root < Resource
|
12
|
-
# Find Redfish service object by OData ID field.
|
13
|
-
#
|
14
|
-
# @param oid [String] Odata id of the resource
|
15
|
-
# @return [Resource, nil] new resource or nil if resource cannot be found
|
16
|
-
def find(oid)
|
17
|
-
find!(oid)
|
18
|
-
rescue NoResource
|
19
|
-
nil
|
20
|
-
end
|
21
|
-
|
22
|
-
# Find Redfish service object by OData ID field.
|
23
|
-
#
|
24
|
-
# @param oid [String] Odata id of the resource
|
25
|
-
# @return [Resource] new resource
|
26
|
-
# @raise [NoResource] resource cannot be fetched
|
27
|
-
def find!(oid)
|
28
|
-
Resource.new(@connector, oid: oid)
|
29
|
-
end
|
30
|
-
|
31
|
-
# Return event listener.
|
32
|
-
#
|
33
|
-
# If the service does not support SSE, this function will return nil.
|
34
|
-
#
|
35
|
-
# @return [EventListener, nil] event listener
|
36
|
-
def event_listener
|
37
|
-
address = dig("EventService", "ServerSentEventUri")
|
38
|
-
return nil if address.nil?
|
39
|
-
|
40
|
-
EventListener.new(ServerSentEvents.create_client(address))
|
41
|
-
end
|
42
|
-
|
43
|
-
# Authenticate against the service.
|
44
|
-
#
|
45
|
-
# Calling this method will select the appropriate method of authentication
|
46
|
-
# and try to login using provided credentials.
|
47
|
-
#
|
48
|
-
# @param username [String] username
|
49
|
-
# @param password [String] password
|
50
|
-
# @raise [RedfishClient::AuthenticatedConnector::AuthError] if user
|
51
|
-
# session could not be authenticated
|
52
|
-
def login(username, password)
|
53
|
-
@connector.set_auth_info(
|
54
|
-
username, password, auth_test_path, session_path
|
55
|
-
)
|
56
|
-
@connector.login
|
57
|
-
end
|
58
|
-
|
59
|
-
# Sign out of the service.
|
60
|
-
def logout
|
61
|
-
@connector.logout
|
62
|
-
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
def session_path
|
67
|
-
# We access raw values here on purpose, since calling dig on resource
|
68
|
-
# instance would try to download the sessions collection, which would
|
69
|
-
# fail since we are not yet logged in.
|
70
|
-
raw.dig("Links", "Sessions", "@odata.id")
|
71
|
-
end
|
72
|
-
|
73
|
-
def auth_test_path
|
74
|
-
raw.values.find { |v| v["@odata.id"] }["@odata.id"]
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
data/lib/redfish_client.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "redfish_client/connector"
|
4
|
-
require "redfish_client/nil_hash"
|
5
|
-
require "redfish_client/root"
|
6
|
-
require "redfish_client/version"
|
7
|
-
|
8
|
-
module RedfishClient
|
9
|
-
# Create new Redfish API client.
|
10
|
-
#
|
11
|
-
# @param url [String] base URL of Redfish API
|
12
|
-
# @param prefix [String] Redfish API prefix
|
13
|
-
# @param verify [Boolean] verify certificates for https connections
|
14
|
-
# @param use_cache [Boolean] cache API responses
|
15
|
-
def self.new(url, prefix: "/redfish/v1", verify: true, use_cache: true)
|
16
|
-
cache = (use_cache ? Hash : NilHash).new
|
17
|
-
con = Connector.new(url, verify: verify, cache: cache)
|
18
|
-
Root.new(con, oid: prefix)
|
19
|
-
end
|
20
|
-
end
|
data/redfish_client.gemspec
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path("../lib", __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require "redfish_client/version"
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "redfish_client"
|
8
|
-
spec.version = RedfishClient::VERSION
|
9
|
-
spec.authors = ["Tadej Borovšak"]
|
10
|
-
spec.email = ["tadej.borovsak@xlab.si"]
|
11
|
-
|
12
|
-
spec.summary = "Simple Redfish client library"
|
13
|
-
spec.homepage = "https://github.com/xlab-steampunk/redfish-client-ruby"
|
14
|
-
spec.license = "Apache-2.0"
|
15
|
-
|
16
|
-
if spec.respond_to?(:metadata)
|
17
|
-
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
18
|
-
else
|
19
|
-
raise "RubyGems 2.0 or newer is required to protect against " \
|
20
|
-
"public gem pushes."
|
21
|
-
end
|
22
|
-
|
23
|
-
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
24
|
-
f.match(%r{^(test|spec|features)/})
|
25
|
-
end
|
26
|
-
spec.bindir = "exe"
|
27
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
-
spec.require_paths = ["lib"]
|
29
|
-
|
30
|
-
spec.required_ruby_version = ">= 2.1"
|
31
|
-
|
32
|
-
spec.add_runtime_dependency "excon", "~> 0.71"
|
33
|
-
spec.add_runtime_dependency "server_sent_events", "~> 0.1"
|
34
|
-
|
35
|
-
spec.add_development_dependency "rake", ">= 11.0"
|
36
|
-
spec.add_development_dependency "rspec", ">= 3.7"
|
37
|
-
spec.add_development_dependency "simplecov"
|
38
|
-
spec.add_development_dependency "webmock", "~> 3.4"
|
39
|
-
spec.add_development_dependency "yard"
|
40
|
-
spec.add_development_dependency "rubocop", "~> 0.54.0"
|
41
|
-
spec.add_development_dependency "pry"
|
42
|
-
end
|