Skip to content
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

Fixed #21204 - introduced global_setting helper function #4891

Merged
merged 1 commit into from
Feb 23, 2018

Conversation

lzap
Copy link
Member

@lzap lzap commented Oct 5, 2017

Locked templates made very difficult to change to discovery in global default templates, user needs to unlock 2+2+2 (PXELinux, Grub, Grub2 template + discovery snippet) and make necessary changes just to change the default menu entry. This can be done via global setting.

This patch adds such a helper function, I am doing changes in community templates to leverage this new function.

Security standpoint - I can't think of any setting that should not be rendered. We do have a root password, but that is already available using the existing helper. Please review with that in mind.

@theforeman-bot
Copy link
Member

There were the following issues with the commit message:

  • c949fc1 must be in the format fixes #redmine_number - brief description

If you don't have a ticket number, please create an issue in Redmine.

More guidelines are available in Coding Standards or on the Foreman wiki.


This message was auto-generated by Foreman's prprocessor

@lzap
Copy link
Member Author

lzap commented Oct 6, 2017

Also added "default_pxe_item_local" so both global and local menu items can be now configured.

@@ -233,6 +252,10 @@ def load_template_vars
@template_url = params['url']
end

def global_setting(name, default = nil)
SETTINGS[name.to_sym] || default
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this was rejected in past because setting contain sensitive information, such as root password for newly provisioned hosts. I suppose we'd need to add a whitelist here. Also the || won't work for settings that has value false, it would always return default value. If you're going to fix this, I'd also suggest renaming global_setting to setting, there's no other setting...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also note that settings page is only available for admins, there's no permission for this. Making it available through template give ability to everyone who can render (preview) template, to see values.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So how about renaming it to "setting", creating whitelist, fixing default value and allowing override via host params, so people can still override this per host/hostgroup.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe is cleaner just to use host/hostgroup parameter for this. That would drop this complexity. But to be honest I really like using settings in templates.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for that is this enables users (or admins specifically) to make discovery the default options. This can't be done with host/hostgroup variables.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that is for admins only, then I think we can drop the host/hg params. Whitelist, default value and renaming is still required I think. I think the whitelist should contain nearly all settings and (sorry to say that), there should be a plugin DSL for extending it. I suppose discovery plugin would require it.

@lzap
Copy link
Member Author

lzap commented Nov 7, 2017

Added whitelist, covered everything with tests, added default list of allowed global options which I think are useful and safe. I did not add those which I thought are not much useful. No host/hostgroup override available, I think this is cleaner.

@lzap
Copy link
Member Author

lzap commented Dec 12, 2017

@ares this is ready for review and merge

Copy link
Member

@iNecas iNecas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for me: don't approve PRs without testing, even when there are unit tests that seem to prove it works.

See comments inline.

@@ -233,6 +277,11 @@ def load_template_vars
@template_url = params['url']
end

def global_setting(name, default = nil)
raise(FilteredGlobalSettingAccessed, _('Global setting "%s" is not accessible in safe-mode') % name) if Setting[:safemode_render] && !ALLOWED_GLOBAL_SETTINGS.include?(name.to_sym)
SETTINGS[name.to_sym] || default
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use Setting, not SETTINGS, the SETTINGS are just for things that come from settings file

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, you should check on blank?, instead of false value. Otherwise, boolean values, such as safemode_render, would not work.

@lzap
Copy link
Member Author

lzap commented Dec 19, 2017

Done, rebased.

Copy link
Member

@dLobatog dLobatog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to be rebased, please @lzap

@lzap
Copy link
Member Author

lzap commented Jan 15, 2018

Rebased.

@@ -59,6 +59,8 @@ def self.default_settings
self.set('dns_conflict_timeout', N_("Timeout for DNS conflict validation (in seconds)"), 3, N_('DNS conflict timeout')),
self.set('clean_up_failed_deployment', N_("Foreman will delete virtual machine if provisioning script ends with non zero exit code"), true, N_('Clean up failed deployment')),
self.set('name_generator_type', N_("Random gives unique names, MAC-based are longer but stable (and only works with bare-metal)"), 'Random-based', N_("Type of name generator"), nil, {:collection => Proc.new {NameGenerator::GENERATOR_TYPES} }),
self.set('default_pxe_item_global', N_("Default PXE (PXELinux, PXEGrub, PXEGrub2) menu item in global template - 'local', 'discovery' or custom"), 'local', N_("Default PXE global template entry")),
self.set('default_pxe_item_local', N_("Default PXE (PXELinux, PXEGrub2) menu item in local template - 'local_chain_hd0', 'local' or custom"), 'local_chain_hd0', N_("Default PXE local template entry")),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how custom is supposed to work? looking at here I'm unable to specify any other value that local/discovery or is that the limitation for grub1?

if custom values are desired, I guess my comment above about limiting the option does not make sense...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grub1 only supports numbers for that option, so there is a small helper array that is then converted to number. I assume that users will sync the array in cloned templates, or simply delete whole thing which does not make much sense in read/write (cloned) template.

I wanted consistent naming in settings across all loaders.

@@ -232,6 +275,11 @@ def load_template_vars
@template_url = params['url']
end

def global_setting(name, default = nil)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the point of having default if setting already provide default? when 2 defaults are useful?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default of default (the option :-) ) is used in templates to have sane default if users does not opt-in and leaves it blank (that's what we ship Foreman with). What do you recommend instead?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't get it, if I use global_settings(:some, 'value'), I'll get value back if there's no Setting[:some]. But in that case, why would I call the global_settings in first place? I'd just use value. Or I'd do global_settigs(:root_pass) || 'change_me' instead of global_settigns(:root_pass, 'change_me')

@lzap
Copy link
Member Author

lzap commented Jan 17, 2018

Rebased, one line changed.

Copy link
Member

@iNecas iNecas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No other comments from me

@lzap
Copy link
Member Author

lzap commented Feb 13, 2018

Thanks @ares @dLobatog are we good to go?

@ares
Copy link
Member

ares commented Feb 13, 2018

@lzap I'd still like to understand the value of default parameter of global_setting but then it's good from my side

@lzap
Copy link
Member Author

lzap commented Feb 15, 2018

While I don't insist on the default option for the helper, I think it might be useful - it's a generic helper after all which can be used for more things. The helper-default will be used when setting is blank meaning that template writers can still provide some default option when user decided to delete the value from settings for some reason. This enables you to add "third state", you can't set nil Ruby value for example via settings, this allows you to create an option "and set to blank for XYZ" and then you can use this mechanism appropriately to set it to nil or any other value - for example an empty array or hash. This can make template code easier to read for example.

So it makes sense, not in this context, but for the future.

@@ -232,6 +275,11 @@ def load_template_vars
@template_url = params['url']
end

def global_setting(name, default = nil)
raise(FilteredGlobalSettingAccessed, _('Global setting "%s" is not accessible in safe-mode') % name) if Setting[:safemode_render] && !ALLOWED_GLOBAL_SETTINGS.include?(name.to_sym)
Setting[name.to_sym].blank? ? default : Setting[name.to_sym]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this does not work well with false (valid value) which is considered blank, I guess the behavior should differ if settings_type is boolean

@ares
Copy link
Member

ares commented Feb 19, 2018

Thanks @lzap, I'm fine with default value now. During testing I found it does not work well with boolean though. After fixing that, thumbs up.

@lzap
Copy link
Member Author

lzap commented Feb 22, 2018

Amended the boolean thing, rebased.

Copy link
Member

@ares ares left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @lzap, works fine now.

@ares ares dismissed dLobatog’s stale review February 23, 2018 06:51

Daniel asked for rebase which was done already

@ares ares merged commit bdcdb09 into theforeman:develop Feb 23, 2018
@lzap lzap deleted the global-setting-21204 branch February 23, 2018 08:37
@lzap
Copy link
Member Author

lzap commented Feb 23, 2018

Thanks, @ares or @dLobatog mind merging theforeman/theforeman.org#1013 discovery docs, so I can carry on with PR that documents this new feature? Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants