-
Notifications
You must be signed in to change notification settings - Fork 87
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
Fixes #8015 - Enable adding defaults options for commands. #174
Conversation
before :each do | ||
HammerCLI::Settings.load(:global_defaults => {:organization_id => 3}) | ||
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.
These tests needs some refinements but I just wanted to check we are on the right track and didn't want to waist a lot of time.
@@ -82,6 +82,14 @@ def self.deep_merge!(h, other_h) | |||
def self.symbolize_hash(h) | |||
h = h.inject({}) { |sym_hash,(k,v)| sym_hash.update(k.to_sym => v) } | |||
end | |||
|
|||
def self.get_defaults_by_key(key, option) |
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'd prefer to keep settings untouched. Could this be moved to separate class and use Settings just as a storage?
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.
Sure ill add a wrapper for it.
Thanks for the update. It looks clean so far. I'd like to see the I don't understand the use-case for global_defaults vs. user_defaults, could you explain, please? I'd also separate the defaults under some key, not to mix with other config stuff: :defaults:
:organization_id: 3
:location_id: 2 Probably not necessary to resolve now, but any idea how to handle name vs. id resource definition? What if user wants to |
OK as for the create commands I still need to implement them I just wanted to make sure I'm going in the right direction first, the create shouldn't problem because i can define it on cli_config under global section or if a resource is given then under the resource. As for generate defaults for plugins, i thought of making a defaults class (will also be the settings wrapper) and on it to have a method generate_defaults(options={}) that will use the create_defaults command to place the options hash to the config file, all the plugins will be able to override and supply their own hash. The global vs resource (user is just an example of a resource), the purpose was to give the users an option to define a default on every request(if the request has the option available) as opposed to placing the default on just one resource. The key separation that i thought of is the _defaults so u'd be able to pretty much define it in any of the config files and all the keys will have the _defaults in the end. About your last point, you think we should deal with that? it wont really be a problem unless the two options have values that don't match. When ever a default value is being used its printed to the screen, so in case of collisions the user will know right away. meanwhile ill add the defaults class and the create option. tell me if you agree on the design so far. |
83c6d5d
to
0a687a6
Compare
:organization_id: 293 | ||
:organization_name: Redhat | ||
:user_defaults: | ||
:organization_id: 2 |
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.
Please nest the options one level deeper so it doesn't mess with other config options. Then the fragile _defaults
suffix is not needed and it can make human editing and even processing more netural.
:defaults:
:_global:
:organization_id: 293
:organization_name: Redhat
:user:
:organization_id: 2
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.
ok, can do that.
I'm not sure about the 'global' vs 'resource related' distinction. Do we have any real use- case for that? |
def self.find_valid_conf_file | ||
path = nil | ||
HammerCLI::Settings.path_history.each do |p| | ||
path = p if p.include?("cli_config.yml") |
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.
Good idea to use the path_history
. It lead me to interesting idea:
I use my hammer to manage multiple foreman/sat instances. It would be nice to have different defaults for each of them as the org_id will probably differ. I usually use hammer -c ~/.hammer/dev.yml commands...
where the dev.yml sets the right url and credentials.
Not sure how to detect the right file in that case though. Or we could put the defaults to separate file and make the path part of the configuration:
:defaults_path: '~/.hammer/dev_defaults.yml'
Then you could create the file for the user if it doesn't exist.
What do you 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.
We can also do that, but the thing is that we said that its better the same file.
I think that for now we can leave it like that, if we would like to change it afterwards, its a small fix.
How common it is for a regular user to manage multiple instances?
Besides the comments above I'd recommend to keep the verbosity as low as possible not to complicate automation. Try to use logger with verbosity of your choice where possible instead of |
OK i agree with you, better putting it in the logger, and ill wrap the strings. |
ee25a80
to
7d7bbb2
Compare
I looked again at the generate defaults command. Would you please explain the purpose and usage of this command? Why |
The defaults add command is for a user to add a defaults setting on his own, the generate is a method that every plugin can override and then it can generate defaults for you(e.g in foreman the generate method will already place org_id and loc_id taken from the web UI) , in every plugin we got for hammer it will be implemented differently. |
Btw how do we want to handle nested params? Let's say I have |
@mbacovsky imho it should assign host to that organization. It should behave the same as when you switch context in UI. |
@mbacovsky I agree with @tstrachota, ill check the reason it's not behaving like that now. |
f1daf20
to
f51fa73
Compare
@mbacovsky @tstrachota changed a bit of the logic on when the defaults are added, and changed the tests accordingly, please give it a check. |
h | ||
self.class.recognised_options.inject({}) do |hash, opt| | ||
hash[opt.attribute_name] = send(opt.read_method) | ||
hash[opt.attribute_name] = context[:defaults].get_defaults(opt.attribute_name) if hash[opt.attribute_name].nil? && context[:defaults] |
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.
Can you keep the logging of the default being used that was present in previous version. It can make bug hunting easier in the future.
@alongoldboim, I like the new location of getting the defaults. It seems more flexible as you can defaults for options that are not comming from API. Well played. It also works fine and the user experience is good. When the logging is added I'm for merging it. 🎺 |
@mbacovsky yea that was part of the idea in moving it there :), thanks, will add logging. |
@mbacovsky @tstrachota added some fixes to improve performance. |
@all_options | ||
end | ||
|
||
def add_custom_defaults(attr) |
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'm still missing the logging of the defaults being used. The add_custom_defaults
is good candidate for doing that:
def add_custom_defaults(attr)
if context[:defaults]
value = context[:defaults].get_defaults(attr)
logger.info("Custom default value #{value} was used for attribute #{attr}") if value
end
value
end
I'd also make it private
, as it is not intended to be part of public command interface
ec43546
to
dbec9e7
Compare
@mbacovsky logger added, moved to private. |
@alongoldboim, thanks! I still need to test it, but it looks good now. |
@alongoldboim It looks good and works as expected now! Thank you. 🍻 👷 |
👍 :) |
end | ||
|
||
describe 'defaults providers' do | ||
header = ['---------|-------------------', |
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.
Tab indentation
@alongoldboim 👍 pending the whitespace issues. Please set your editor to use spaces instead of tabs. |
First patch replacing tabs with spaces reuse directory constant - it should be defined at a single place to avoid complications when there's need to rename - such constants should be extracted from translation strings fixed indentation variables renamed to more meaningful names - just a cosmetic thing - you had the file contents named file which I found confusing removed comment that was no longer true defaults moved to context - avoids mocking the global defaults class which makes testing a lot easier. See my next commit with tests. adding tests for the commands - before they weren't tested at all assert_equal takes expected value as the first parameter - in assertions the first parameter is always the expected one - see for example http://ruby-doc.org/stdlib-2.0.0/libdoc/minitest/rdoc/MiniTest/Assertions.html fixing test that actually tested only the mocking mechanism - changed data of one test to make sure the tested modification actually happens. Before it was in the expected state already. - "should get the default param, with provider" actually only tested mocking use specific exceptions - formerly used NameError can be raised also when a method is missing, which makes debugging more difficult - similar goes for StandardError use instance of defaults - allows for injecting the filename - no need to pollute the global defaults when testing it
@tstrachota @mbacovsky done deal. |
@alongoldboim Thanks, merging!!! 🍸 |
Fixes #8015 - Enable adding defaults options for commands.
To add default option to your hammer cli commands you need to define the key value pair(e.g organization_id: 3) under global_defaults in the cli_config.yml(the option will be added if the command permits it in its options).
you can specify a particular resource you want the default option will take effected on by placing the key value pair under _defauls, this can be done either in the cli_config.yml or in any other plugin config file(e.g foreman.yml).
Need to add a generate defaults command according to plugin and a managing command(add,remove).