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

Unify config #38

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

Unify config #38

wants to merge 8 commits into from

Conversation

reidmv
Copy link
Collaborator

@reidmv reidmv commented Jun 13, 2017

Builds on #37.

This is effectively a cleanup of the way config options work. Any config option can now be read from a file, OR passed on the CLI. Valid config options must be specified as part of the SETTINGS array.

files/tk_metrics Outdated
clientcert: { type: :string },
pe_version: { type: :string },
print: { type: :boolean },
ssl: { type: :boolean },
Copy link
Owner

@npwalker npwalker Jun 13, 2017

Choose a reason for hiding this comment

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

What happens if ssl is not specified in the config file or on the CLI? It currently defaults to true if unspecified

files/tk_metrics Outdated
options = {}
#===========================================================================#
# BUILD CONFIGURATION OPTIONS #
#===========================================================================#
Copy link
Owner

Choose a reason for hiding this comment

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

Are you planning on doing anything with amq_metrics?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not in this PR, no. But yeah, if this works here it's a forkliftable pattern.

@reidmv
Copy link
Collaborator Author

reidmv commented Jun 13, 2017

@npwalker Added defaults to the configs.

files/tk_metrics Outdated
metrics: { type: :list },
clientcert: { type: :string },
pe_version: { type: :string },
print: { type: :boolean, default: false },
Copy link
Owner

Choose a reason for hiding this comment

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

print defaults to true.

files/tk_metrics Outdated
SETTINGS = {
output_dir: { type: :string },
hosts: { type: :list },
port: { type: :string },
Copy link
Owner

@npwalker npwalker Jun 13, 2017

Choose a reason for hiding this comment

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

I'm not 100% convinced that metrics will always run on the same port as the status endpoint so I don't see a need to rename this to port.

If we decide to allow running the status endpoint on a different port so that even when a component is overloaded we can still get the status output then I'd like to be able to have metrics_port and status_port.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Makes sense. Changed it back to metrics_port.

files/tk_metrics Outdated
REQUIRED_FLAGS.merge(SETTINGS).each do |opt,attrs|
case attrs[:type]
when :string, nil
opts.on("--#{opt} ARG", '(no description)') { |arg| config[opt] = arg }
Copy link
Owner

Choose a reason for hiding this comment

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

Are descriptions not useful in the --help output?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

They can be, yeah. This comment prompted a semi-big rewrite of the consolidation. New commits pushed.

@reidmv reidmv force-pushed the unify_config branch 2 times, most recently from c38a27a to 5d2bf7a Compare June 13, 2017 21:45
reidmv added 3 commits June 14, 2017 10:38
So that any config option can be specified on the CLI, or read from the
file.
This aligns the CLI more closely with modern Puppet tooling. Also, we've
used --config-dir with a hyphen already, so deciding on and choosing a
consistent word separator seems like a postivie thing.
Descriptions can be nice. As a side effect the code is probably simpler
too.

Also revert opt "metrics" back to "additional-metrics" Well, "back to"
is a bit strong since the original was "additional_metrics". Still, the
idea's the same. It's more correct given what the parameter is for /
does.
Rather than making a human type an option name twice, add another lambda
to generate the option string based on argument type - value or boolean.
files/tk_metrics Outdated
option = lambda do |name,desc,fopt,fsave,default=nil|
settings[name] = { default: default }
parser.on(fopt.call(name.to_s), desc) do |arg|
fsave.call(name, arg)
Copy link
Owner

Choose a reason for hiding this comment

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

If I'm understanding this correctly... is this really saving code / increasing clarity over?

if fsave == 'ident' then 
  config[name] = arg 
else if fsave == 'list' then 
  config[name] = arg.split(',')
end

not guaranteed to compile

Copy link
Owner

Choose a reason for hiding this comment

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

or maybe just

if fsave == 'list' then
  config[name] = arg.split(',')
else 
  config[name] = arg 
end

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think it's just a difference between a functional style and a procedural style. I like the functional style, but I'm sure a procedural equivalent could be done too. I originally chose functional because I wanted to clearly contain all of the logic for how to build out config options (starts on line 33) INSIDE the OptionParser#new block, not rely on any external def's, and not do any weird scoped def's inside the block. Since I was doing one lambda anyway I figured I'd go all-in on the functional.

files/tk_metrics Outdated
option.call(:"metrics-type", 'Type of metric to collect', opt_value, save_ident)

# Kinda pointless to include descriptions unless there's a help flag
parser.on("-h", "--help", "Prints this help") { puts parser; exit }
Copy link
Owner

Choose a reason for hiding this comment

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

I think you just get this for free. The current implementation has it.

[root@master201646-centos puppet_enterprise]# /opt/puppetlabs/pe_metric_curl_cron_jobs/scripts/tk_metrics --help
Usage: tk_metrics [options]
    -p, --[no-]print                 Print to stdout
    -m, --metrics_type [TYPE]        Type of metric to collect
    -o, --output-dir [DIR]           Directory to save output to
        --metrics_port [PORT]        The port the metrics service runs on
        --[no-]ssl                   Whether or not to use SSL when gather metrics
[root@master201646-centos puppet_enterprise]# /opt/puppetlabs/pe_metric_curl_cron_jobs/scripts/tk_metrics -h
Usage: tk_metrics [options]
    -p, --[no-]print                 Print to stdout
    -m, --metrics_type [TYPE]        Type of metric to collect
    -o, --output-dir [DIR]           Directory to save output to
        --metrics_port [PORT]        The port the metrics service runs on
        --[no-]ssl                   Whether or not to use SSL when gather metrics

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I added this when I tried -h and it didn't work. Does -h work for you without it?

Copy link
Owner

Choose a reason for hiding this comment

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

Anything short of help and help itself seems to work.

[root@master201646-centos puppet_enterprise]# /opt/puppetlabs/pe_metric_curl_cron_jobs/scripts/tk_metrics -h
Usage: tk_metrics [options]
    -p, --[no-]print                 Print to stdout
    -m, --metrics_type [TYPE]        Type of metric to collect
    -o, --output-dir [DIR]           Directory to save output to
        --metrics_port [PORT]        The port the metrics service runs on
        --[no-]ssl                   Whether or not to use SSL when gather metrics
[root@master201646-centos puppet_enterprise]# /opt/puppetlabs/pe_metric_curl_cron_jobs/scripts/tk_metrics --help
Usage: tk_metrics [options]
    -p, --[no-]print                 Print to stdout
    -m, --metrics_type [TYPE]        Type of metric to collect
    -o, --output-dir [DIR]           Directory to save output to
        --metrics_port [PORT]        The port the metrics service runs on
        --[no-]ssl                   Whether or not to use SSL when gather metrics
[root@master201646-centos puppet_enterprise]# /opt/puppetlabs/pe_metric_curl_cron_jobs/scripts/tk_metrics --h
Usage: tk_metrics [options]
    -p, --[no-]print                 Print to stdout
    -m, --metrics_type [TYPE]        Type of metric to collect
    -o, --output-dir [DIR]           Directory to save output to
        --metrics_port [PORT]        The port the metrics service runs on
        --[no-]ssl                   Whether or not to use SSL when gather metrics
[root@master201646-centos puppet_enterprise]# /opt/puppetlabs/pe_metric_curl_cron_jobs/scripts/tk_metrics --he
Usage: tk_metrics [options]
    -p, --[no-]print                 Print to stdout
    -m, --metrics_type [TYPE]        Type of metric to collect
    -o, --output-dir [DIR]           Directory to save output to
        --metrics_port [PORT]        The port the metrics service runs on
        --[no-]ssl                   Whether or not to use SSL when gather metrics
[root@master201646-centos puppet_enterprise]# /opt/puppetlabs/pe_metric_curl_cron_jobs/scripts/tk_metrics --blah
/opt/puppetlabs/pe_metric_curl_cron_jobs/scripts/tk_metrics:19:in `<main>': invalid option: --blah (OptionParser::InvalidOption)
[root@master201646-centos puppet_enterprise]# /opt/puppetlabs/pe_metric_curl_cron_jobs/scripts/tk_metrics --hel
Usage: tk_metrics [options]
    -p, --[no-]print                 Print to stdout
    -m, --metrics_type [TYPE]        Type of metric to collect
    -o, --output-dir [DIR]           Directory to save output to
        --metrics_port [PORT]        The port the metrics service runs on
        --[no-]ssl                   Whether or not to use SSL when gather metrics
[root@master201646-centos puppet_enterprise]# /opt/puppetlabs/pe_metric_curl_cron_jobs/scripts/tk_metrics --helps
/opt/puppetlabs/pe_metric_curl_cron_jobs/scripts/tk_metrics:19:in `<main>': invalid option: --helps (OptionParser::InvalidOption)
[root@master201646-centos puppet_enterprise]# /opt/puppetlabs/pe_metric_curl_cron_jobs/scripts/tk_metrics -help
Usage: tk_metrics [options]
    -p, --[no-]print                 Print to stdout
    -m, --metrics_type [TYPE]        Type of metric to collect
    -o, --output-dir [DIR]           Directory to save output to
        --metrics_port [PORT]        The port the metrics service runs on
        --[no-]ssl                   Whether or not to use SSL when gather metrics
[root@master201646-centos puppet_enterprise]# /opt/puppetlabs/pe_metric_curl_cron_jobs/scripts/tk_metrics -hel
Usage: tk_metrics [options]
    -p, --[no-]print                 Print to stdout
    -m, --metrics_type [TYPE]        Type of metric to collect
    -o, --output-dir [DIR]           Directory to save output to
        --metrics_port [PORT]        The port the metrics service runs on
        --[no-]ssl                   Whether or not to use SSL when gather metrics
[root@master201646-centos puppet_enterprise]# /opt/puppetlabs/pe_metric_curl_cron_jobs/scripts/tk_metrics -he
Usage: tk_metrics [options]
    -p, --[no-]print                 Print to stdout
    -m, --metrics_type [TYPE]        Type of metric to collect
    -o, --output-dir [DIR]           Directory to save output to
        --metrics_port [PORT]        The port the metrics service runs on
        --[no-]ssl                   Whether or not to use SSL when gather metrics
[root@master201646-centos puppet_enterprise]# /opt/puppetlabs/pe_metric_curl_cron_jobs/scripts/tk_metrics -h
Usage: tk_metrics [options]
    -p, --[no-]print                 Print to stdout
    -m, --metrics_type [TYPE]        Type of metric to collect
    -o, --output-dir [DIR]           Directory to save output to
        --metrics_port [PORT]        The port the metrics service runs on
        --[no-]ssl                   Whether or not to use SSL when gather metrics

files/tk_metrics Outdated

end.parse!

raise('ERROR: Missing configuration option "metrics-type"') if config[:"metrics-type"].nil?
Copy link
Owner

Choose a reason for hiding this comment

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

I assume this equates to the below. Pure curiosity, why is this preferred?

if config[:"metrics-type"].nil?
  raise('ERROR: Missing configuration option "metrics-type"')
end

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's an interesting question, I don't know. At some point I got used to writing "abort"-type statements in a way that emphasized the abort part over the if part. Happy to switch it around if you prefer the above.

Copy link
Owner

Choose a reason for hiding this comment

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

This feels as though it could be one of those Rubyisms. I find some rubyisms strange but I may just not be that familiar with it. Was mostly a curiosity question we can leave it

files/tk_metrics Outdated
# command line are given precedence.
settings.each do |opt,attrs|
possibilities = [config[opt], file_config[opt], attrs[:default]]
config[opt] = possibilities.find {|p| !p.nil? }
Copy link
Owner

Choose a reason for hiding this comment

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

Thoughts on reading in the config file before parsing command line args. Then you can check

if the command line arg is nil
use the config file setting
if the config file setting is nil use the default
else fail

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'd like to change how the config file works. What I most want to do is allow a config file path to be specified as an option flag. Regardless though, it's currently difficult to parse a config file first since the config file location depends on a flag (--metrics-type or maybe --config), and I don't know if there's a way for optparse to find and evaluate a particular flag first. I think it evaluates flags in the order they're given on the command line...

Make a new option, --config, which is used to directly specify the
configuration file to use. Also clean up the variable names so the code
is easier to follow in terms of what it's doing.

The old behavior where --metrics-type implied a config file name is
still supported as legacy.
@reidmv
Copy link
Collaborator Author

reidmv commented Jun 15, 2017

@npwalker added a commit that should simplify a bit how the config file works.

files/tk_metrics Outdated
option.call(:"metrics-type", 'Type of metric to collect', opt_value, save_ident)

# Kinda pointless to include descriptions unless there's a help flag
parser.on("-h", "--help", "Prints this help") { puts parser; exit }

end.parse!

raise('ERROR: Missing configuration option "metrics-type"') if config[:"metrics-type"].nil?
# This is to support legacy from the time when passing --metrics-type was what
# determined the filename of the config file, rather than the --config option.
Copy link
Owner

Choose a reason for hiding this comment

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

Is this important? I'm inclined to just switch to --config not support just --metrics-type on its own

@reidmv reidmv force-pushed the unify_config branch 4 times, most recently from 9d228ab to a2e1df5 Compare June 15, 2017 22:50
The script must now be invoked with the --config option to specify a
configuration file, OR all required configuration parameters must be
passed as command-line flags.

Because this involves a change in the API to interact with the script,
the amq_metrics script is now in scope also, and has had the same option
parsing interface applied to it.
@reidmv
Copy link
Collaborator Author

reidmv commented Jul 10, 2017

@npwalker bump

Dir.mkdir(host) unless File.exist?(host)
File.open(File.join(host, filename), 'w') do |file|
file.write(json_dataset)
end
end
end
if options[:print] != false then
if config[:print] then
Copy link
Owner

Choose a reason for hiding this comment

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

The default behavior of the script is currently to print. I think this breaks that unless you've defaulted print to true somehow. Will test.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Option definition is on line 41. Default value is True.

files/tk_metrics Outdated

json_dataset = JSON.pretty_generate(dataset)

unless OUTPUT_DIR.nil? then
Dir.chdir(OUTPUT_DIR) do
unless config[:"output-dir"] == false then
Copy link
Owner

Choose a reason for hiding this comment

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

output-dir is a path not a boolean?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yep. With a default value of False. Part of the option definition on line 35. Could probably change it to a symbol like :undef, should have roughly the same effect. This if-statement is just checking to see if the option has a valid value, or if it's the not-nil-but-not-valid default.

Copy link
Owner

Choose a reason for hiding this comment

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

@reidmv is there a reason we can't just leave unset options nil and check them for being nil?

I certainly do find giving something a default of false when it's expected to be a path to be confusing.

files/tk_metrics Outdated
Dir.mkdir(host) unless File.exist?(host)
File.open(File.join(host, filename), 'w') do |file|
file.write(json_dataset)
end
end
end
if options[:print] != false then
if config[:print] != false then
Copy link
Owner

Choose a reason for hiding this comment

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

this doesn't match the amq script

Previously some optional values had a default value of False. In order
to indicate that the user doesn't need to supply a value a default is
required, but False as the default did not make it clear that the value
simply hadn't been supplied.

This commit switches such values to use :undef as their default instead,
thus making it clearer what is happening.
@reidmv
Copy link
Collaborator Author

reidmv commented Aug 1, 2017

@npwalker Cleaned up based on comments. Unsupplied, optional values now default to :undef instead of false. Treatment of config[:print] made uniform across the two scripts.

@reidmv
Copy link
Collaborator Author

reidmv commented Sep 12, 2017

@npwalker ping - needs decision

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

Successfully merging this pull request may close these issues.

2 participants