-
Notifications
You must be signed in to change notification settings - Fork 898
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
API Enhancement to support fine-grained settings whitelisting #13948
API Enhancement to support fine-grained settings whitelisting #13948
Conversation
Marked as WIP
|
This is a prototype for the enhancement I briefly referred to. It allows the API to expose a subset of the settings tree, down to an individual entry, and allows the users to be able to fetch any particular entry and not just top level category (i.e. GET /api/settings/product) with is a current limitation. For David's use, we can update the config/api.yml to expose the additional entries he needs as well as others as follows:
And with this PR: a GET of the settings collection:
will return the exposed settings subtree as follows:
One can fetch just the server subtree:
Or simply the entry of interest:
|
41ca011
to
c22ac82
Compare
@imtayadeway @gtanzillo please review. Thanks!! |
c22ac82
to
0d5a8b8
Compare
spec/requests/api/settings_spec.rb
Outdated
run_get settings_url | ||
|
||
expect(response.parsed_body).to match( | ||
"product" => normalize_settings(Settings.product), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if we stubbed the Settings
constant as below, we'd have more control over this. Then you could see in these tests that you're getting back the values you expected. This test gives me low confidence, because it's verifying against something that's not specified (Settings.product
etc.., whatever these values may be), and it's also munging those values with untested code (normalize_hash
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct, if we have a declared Settings hash (without symbol or nil data), the normalize_hash wouldn't be needed. It was written as to make sure the Settings returned is how the API would have rendered it.
end | ||
|
||
private | ||
|
||
def exposed_settings | ||
ApiConfig.collections[:settings][:categories] | ||
def whitelist_settings(settings) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems (a) sufficiently complicated, and (b) already abstracted away from details of the request to warrant a service object that could be perhaps better tested in isolation. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is coded as it's needed as such by a following PR. Some of this code will be moving to an API Settings mixin, will be used by servers, regions and zones.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I follow. Is there a problem with delegating?
Not sure I get the workflow around configurable categories. Is it designed to be configurable by the end user? How would they configure it, by updating the yml file by hand? |
def settings_entry_to_hash(path, value) | ||
path_elements = path.split("/") | ||
result_hash = {path_elements.last => value} | ||
path_elements[0..-2].reverse.each { |entry| result_hash = { entry => result_hash } } if path_elements.length > 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be cleaner if you just start with the value and iterate from there.
def settings_entry_to_hash(path, value)
result = value
path.split("/").reverse.each { |entry| result = {entry => result} }
result
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, now that I think about it, just use store_path
def settings_entry_to_hash(path, value)
{}.tap { |h| h.store_path(path.split("/"), value) }
end
Example
path = "foo/bar/baz"
value = 1234
{}.tap { |h| h.store_path(path.split("/"), value) }
# => {"foo"=>{"bar"=>{"baz"=>1234}}}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additionally, if you're just using store_path, then you can avoid the create-entry-and-deep-merge-loop I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, didn't know about store_path, NICE !! I'll update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deep_merge was still needed with categories like server/role, server/worker_monitor, ...
0d5a8b8
to
ebdce57
Compare
@imtayadeway as discussed yesterday, see updated tests, much simpler. Thanks!! |
categories like it does today like product, authentication, server, but also sub pathing, server/role, session/timeout even lower level entries like server/worker_monitor/start_algorithm/value - whitelists a subset of the settings as driven by the new categories - Can fetch top level categories or any setting entry path: GET /api/settings/product, or GET /api/settings/server/role (if exposed) - Added rspecs
and thus queried by the API eliminating the need for Settings normalization on the responses in the tests.
settings categories via the method stub_api_settings_categories. - Moved the method to within the settings_spec.rb's tests
d2912c5
to
86cd8ff
Compare
Checked commits abellotti/manageiq@7df0015~...86cd8ff with ruby 2.2.6, rubocop 0.47.1, and haml-lint 0.20.0 |
Adding support for arbitrary path categories, can include top level categories like it does today like product, authentication, server, but also sub pathing, server/role, session/timeout even lower level entries like server/worker_monitor/start_algorithm/value
Exposes the subset of the settings as driven by the new categories
Can fetch top level categories or any setting entry path:
GET /api/settings/product, or GET /api/settings/server/role (if exposed)
Added rspecs