Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions otava/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,14 @@ def add_service_option_groups(parser) -> None:
BigQueryConfig.add_parser_args(parser.add_argument_group('BigQuery Options', 'Options for BigQuery configuration'))


def create_subparser_parent() -> configargparse.ArgumentParser:
"""Create a parent parser for subparsers that accepts --config-file and service options."""
parent = configargparse.ArgumentParser(add_help=False)
parent.add_argument('--config-file', help='Otava config file path', env_var="OTAVA_CONFIG")
add_service_option_groups(parent)
return parent


def create_config_parser() -> configargparse.ArgumentParser:
parser = configargparse.ArgumentParser(
add_help=False,
Expand Down
18 changes: 10 additions & 8 deletions otava/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,33 +457,35 @@ def create_otava_cli_parser() -> argparse.ArgumentParser:
allow_abbrev=False, # required for correct parsing of nested values from config file
)

subparser_parent = config.create_subparser_parent()

subparsers = parser.add_subparsers(dest="command")
list_tests_parser = subparsers.add_parser(
"list-tests",
help="list available tests",
parents=[subparser_parent],
)
config.add_service_option_groups(list_tests_parser)
list_tests_parser.add_argument("group", help="name of the group of the tests", nargs="*")

list_metrics_parser = subparsers.add_parser(
"list-metrics",
help="list available metrics for a test",
parents=[subparser_parent],
)
config.add_service_option_groups(list_metrics_parser)
list_metrics_parser.add_argument("test", help="name of the test")

list_groups_parser = subparsers.add_parser(
subparsers.add_parser(
"list-groups",
help="list available groups of tests",
parents=[subparser_parent],
)
config.add_service_option_groups(list_groups_parser)

analyze_parser = subparsers.add_parser(
"analyze",
help="analyze performance test results",
parents=[subparser_parent],
)
analyze_parser.add_argument("tests", help="name of the test or group of the tests", nargs="+")
config.add_service_option_groups(analyze_parser)
analyze_parser.add_argument(
"--update-grafana",
help="Update Grafana dashboards with appropriate annotations of change points",
Expand Down Expand Up @@ -523,20 +525,20 @@ def create_otava_cli_parser() -> argparse.ArgumentParser:

remove_annotations_parser = subparsers.add_parser(
"remove-annotations",
parents=[subparser_parent],
)
config.add_service_option_groups(remove_annotations_parser)
remove_annotations_parser.add_argument(
"tests", help="name of the test or test group", nargs="*"
)
remove_annotations_parser.add_argument(
"--force", help="don't ask questions, just do it", dest="force", action="store_true"
)

validate_parser = subparsers.add_parser(
subparsers.add_parser(
"validate",
help="validates the tests and metrics defined in the configuration",
parents=[subparser_parent],
)
config.add_service_option_groups(validate_parser)

return parser

Expand Down
139 changes: 54 additions & 85 deletions tests/cli_help_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,81 +133,34 @@ def test_otava_analyze_help_output():
f"Expected exit code 0, got {result.returncode}. stderr:\n{result.stderr}"
)

# Python 3.13+ formats usage lines and option aliases differently
# Python 3.13+ formats mutually exclusive group usage and option aliases differently
if IS_PYTHON_313_PLUS:
usage_and_options = """\
usage: otava analyze [-h] [--graphite-url GRAPHITE_URL] [--grafana-url GRAFANA_URL]
[--grafana-user GRAFANA_USER] [--grafana-password GRAFANA_PASSWORD]
[--slack-token SLACK_TOKEN] [--postgres-hostname POSTGRES_HOSTNAME]
[--postgres-port POSTGRES_PORT] [--postgres-username POSTGRES_USERNAME]
[--postgres-password POSTGRES_PASSWORD]
[--postgres-database POSTGRES_DATABASE]
[--bigquery-project-id BIGQUERY_PROJECT_ID]
[--bigquery-dataset BIGQUERY_DATASET]
[--bigquery-credentials BIGQUERY_CREDENTIALS] [--update-grafana]
[--update-postgres] [--update-bigquery]
[--notify-slack NOTIFY_SLACK [NOTIFY_SLACK ...]] [--cph-report-since DATE]
[--output {log,json,regressions_only}] [--branch [STRING]] [--metrics LIST]
usage_filter_lines = """\
[--attrs LIST] [--since-commit STRING | --since-version STRING |
--since DATE] [--until-commit STRING | --until-version STRING | --until DATE]
[--last COUNT] [-P, --p-value PVALUE] [-M MAGNITUDE] [--window WINDOW]
[--orig-edivisive ORIG_EDIVISIVE]
tests [tests ...]

positional arguments:
tests name of the test or group of the tests

options:
-h, --help show this help message and exit
--update-grafana Update Grafana dashboards with appropriate annotations of change points
--update-postgres Update PostgreSQL database results with change points
--update-bigquery Update BigQuery database results with change points
--notify-slack NOTIFY_SLACK [NOTIFY_SLACK ...]
Send notification containing a summary of change points to given Slack
channels
--cph-report-since DATE
Sets a limit on the date range of the Change Point History reported to
Slack. Same syntax as --since.
--output {log,json,regressions_only}
Output format for the generated report.
--branch [STRING] name of the branch [env var: BRANCH]
--metrics LIST a comma-separated list of metrics to analyze
--attrs LIST a comma-separated list of attribute names associated with the runs (e.g.
commit, branch, version); if not specified, it will be automatically
filled based on available information
--since-commit STRING
the commit at the start of the time span to analyze
--since-version STRING
the version at the start of the time span to analyze
--since DATE the start of the time span to analyze; accepts ISO, and human-readable
dates like '10 weeks ago'
--until-commit STRING
the commit at the end of the time span to analyze
--until-version STRING
the version at the end of the time span to analyze
--until DATE the end of the time span to analyze; same syntax as --since
--last COUNT the number of data points to take from the end of the series
-P, --p-value PVALUE maximum accepted P-value of a change-point; P denotes the probability that
the change-point has been found by a random coincidence, rather than a
real difference between the data distributions
-M, --magnitude MAGNITUDE"""
--since DATE] [--until-commit STRING | --until-version STRING | --until DATE]"""
magnitude_option = " -M, --magnitude MAGNITUDE"
else:
usage_and_options = """\
usage: otava analyze [-h] [--graphite-url GRAPHITE_URL] [--grafana-url GRAFANA_URL]
[--grafana-user GRAFANA_USER] [--grafana-password GRAFANA_PASSWORD]
[--slack-token SLACK_TOKEN] [--postgres-hostname POSTGRES_HOSTNAME]
[--postgres-port POSTGRES_PORT] [--postgres-username POSTGRES_USERNAME]
usage_filter_lines = """\
[--attrs LIST]
[--since-commit STRING | --since-version STRING | --since DATE]
[--until-commit STRING | --until-version STRING | --until DATE]"""
magnitude_option = " -M MAGNITUDE, --magnitude MAGNITUDE"

usage_and_options = f"""\
usage: otava analyze [-h] [--config-file CONFIG_FILE] [--graphite-url GRAPHITE_URL]
[--grafana-url GRAFANA_URL] [--grafana-user GRAFANA_USER]
[--grafana-password GRAFANA_PASSWORD] [--slack-token SLACK_TOKEN]
[--postgres-hostname POSTGRES_HOSTNAME] [--postgres-port POSTGRES_PORT]
[--postgres-username POSTGRES_USERNAME]
[--postgres-password POSTGRES_PASSWORD]
[--postgres-database POSTGRES_DATABASE]
[--bigquery-project-id BIGQUERY_PROJECT_ID]
[--bigquery-dataset BIGQUERY_DATASET]
[--bigquery-credentials BIGQUERY_CREDENTIALS] [--update-grafana]
[--update-postgres] [--update-bigquery]
[--notify-slack NOTIFY_SLACK [NOTIFY_SLACK ...]] [--cph-report-since DATE]
[--output {log,json,regressions_only}] [--branch [STRING]] [--metrics LIST]
[--attrs LIST]
[--since-commit STRING | --since-version STRING | --since DATE]
[--until-commit STRING | --until-version STRING | --until DATE]
[--output {{log,json,regressions_only}}] [--branch [STRING]] [--metrics LIST]
{usage_filter_lines}
[--last COUNT] [-P, --p-value PVALUE] [-M MAGNITUDE] [--window WINDOW]
[--orig-edivisive ORIG_EDIVISIVE]
tests [tests ...]
Expand All @@ -217,6 +170,8 @@ def test_otava_analyze_help_output():

options:
-h, --help show this help message and exit
--config-file CONFIG_FILE
Otava config file path [env var: OTAVA_CONFIG]
--update-grafana Update Grafana dashboards with appropriate annotations of change points
--update-postgres Update PostgreSQL database results with change points
--update-bigquery Update BigQuery database results with change points
Expand All @@ -226,7 +181,7 @@ def test_otava_analyze_help_output():
--cph-report-since DATE
Sets a limit on the date range of the Change Point History reported to
Slack. Same syntax as --since.
--output {log,json,regressions_only}
--output {{log,json,regressions_only}}
Output format for the generated report.
--branch [STRING] name of the branch [env var: BRANCH]
--metrics LIST a comma-separated list of metrics to analyze
Expand All @@ -248,7 +203,7 @@ def test_otava_analyze_help_output():
-P, --p-value PVALUE maximum accepted P-value of a change-point; P denotes the probability that
the change-point has been found by a random coincidence, rather than a
real difference between the data distributions
-M MAGNITUDE, --magnitude MAGNITUDE"""
{magnitude_option}"""

assert (
result.stdout
Expand Down Expand Up @@ -324,10 +279,11 @@ def test_otava_list_tests_help_output():
assert (
result.stdout
== """\
usage: otava list-tests [-h] [--graphite-url GRAPHITE_URL] [--grafana-url GRAFANA_URL]
[--grafana-user GRAFANA_USER] [--grafana-password GRAFANA_PASSWORD]
[--slack-token SLACK_TOKEN] [--postgres-hostname POSTGRES_HOSTNAME]
[--postgres-port POSTGRES_PORT] [--postgres-username POSTGRES_USERNAME]
usage: otava list-tests [-h] [--config-file CONFIG_FILE] [--graphite-url GRAPHITE_URL]
[--grafana-url GRAFANA_URL] [--grafana-user GRAFANA_USER]
[--grafana-password GRAFANA_PASSWORD] [--slack-token SLACK_TOKEN]
[--postgres-hostname POSTGRES_HOSTNAME] [--postgres-port POSTGRES_PORT]
[--postgres-username POSTGRES_USERNAME]
[--postgres-password POSTGRES_PASSWORD]
[--postgres-database POSTGRES_DATABASE]
[--bigquery-project-id BIGQUERY_PROJECT_ID]
Expand All @@ -340,6 +296,8 @@ def test_otava_list_tests_help_output():

options:
-h, --help show this help message and exit
--config-file CONFIG_FILE
Otava config file path [env var: OTAVA_CONFIG]

Graphite Options:
Options for Graphite configuration
Expand Down Expand Up @@ -401,10 +359,11 @@ def test_otava_list_metrics_help_output():
assert (
result.stdout
== """\
usage: otava list-metrics [-h] [--graphite-url GRAPHITE_URL] [--grafana-url GRAFANA_URL]
[--grafana-user GRAFANA_USER] [--grafana-password GRAFANA_PASSWORD]
[--slack-token SLACK_TOKEN] [--postgres-hostname POSTGRES_HOSTNAME]
[--postgres-port POSTGRES_PORT] [--postgres-username POSTGRES_USERNAME]
usage: otava list-metrics [-h] [--config-file CONFIG_FILE] [--graphite-url GRAPHITE_URL]
[--grafana-url GRAFANA_URL] [--grafana-user GRAFANA_USER]
[--grafana-password GRAFANA_PASSWORD] [--slack-token SLACK_TOKEN]
[--postgres-hostname POSTGRES_HOSTNAME] [--postgres-port POSTGRES_PORT]
[--postgres-username POSTGRES_USERNAME]
[--postgres-password POSTGRES_PASSWORD]
[--postgres-database POSTGRES_DATABASE]
[--bigquery-project-id BIGQUERY_PROJECT_ID]
Expand All @@ -417,6 +376,8 @@ def test_otava_list_metrics_help_output():

options:
-h, --help show this help message and exit
--config-file CONFIG_FILE
Otava config file path [env var: OTAVA_CONFIG]

Graphite Options:
Options for Graphite configuration
Expand Down Expand Up @@ -479,10 +440,11 @@ def test_otava_list_groups_help_output():
assert (
result.stdout
== """\
usage: otava list-groups [-h] [--graphite-url GRAPHITE_URL] [--grafana-url GRAFANA_URL]
[--grafana-user GRAFANA_USER] [--grafana-password GRAFANA_PASSWORD]
[--slack-token SLACK_TOKEN] [--postgres-hostname POSTGRES_HOSTNAME]
[--postgres-port POSTGRES_PORT] [--postgres-username POSTGRES_USERNAME]
usage: otava list-groups [-h] [--config-file CONFIG_FILE] [--graphite-url GRAPHITE_URL]
[--grafana-url GRAFANA_URL] [--grafana-user GRAFANA_USER]
[--grafana-password GRAFANA_PASSWORD] [--slack-token SLACK_TOKEN]
[--postgres-hostname POSTGRES_HOSTNAME] [--postgres-port POSTGRES_PORT]
[--postgres-username POSTGRES_USERNAME]
[--postgres-password POSTGRES_PASSWORD]
[--postgres-database POSTGRES_DATABASE]
[--bigquery-project-id BIGQUERY_PROJECT_ID]
Expand All @@ -491,6 +453,8 @@ def test_otava_list_groups_help_output():

options:
-h, --help show this help message and exit
--config-file CONFIG_FILE
Otava config file path [env var: OTAVA_CONFIG]

Graphite Options:
Options for Graphite configuration
Expand Down Expand Up @@ -552,8 +516,8 @@ def test_otava_remove_annotations_help_output():
assert (
result.stdout
== """\
usage: otava remove-annotations [-h] [--graphite-url GRAPHITE_URL] [--grafana-url GRAFANA_URL]
[--grafana-user GRAFANA_USER]
usage: otava remove-annotations [-h] [--config-file CONFIG_FILE] [--graphite-url GRAPHITE_URL]
[--grafana-url GRAFANA_URL] [--grafana-user GRAFANA_USER]
[--grafana-password GRAFANA_PASSWORD] [--slack-token SLACK_TOKEN]
[--postgres-hostname POSTGRES_HOSTNAME]
[--postgres-port POSTGRES_PORT]
Expand All @@ -570,6 +534,8 @@ def test_otava_remove_annotations_help_output():

options:
-h, --help show this help message and exit
--config-file CONFIG_FILE
Otava config file path [env var: OTAVA_CONFIG]
--force don't ask questions, just do it

Graphite Options:
Expand Down Expand Up @@ -632,10 +598,11 @@ def test_otava_validate_help_output():
assert (
result.stdout
== """\
usage: otava validate [-h] [--graphite-url GRAPHITE_URL] [--grafana-url GRAFANA_URL]
[--grafana-user GRAFANA_USER] [--grafana-password GRAFANA_PASSWORD]
[--slack-token SLACK_TOKEN] [--postgres-hostname POSTGRES_HOSTNAME]
[--postgres-port POSTGRES_PORT] [--postgres-username POSTGRES_USERNAME]
usage: otava validate [-h] [--config-file CONFIG_FILE] [--graphite-url GRAPHITE_URL]
[--grafana-url GRAFANA_URL] [--grafana-user GRAFANA_USER]
[--grafana-password GRAFANA_PASSWORD] [--slack-token SLACK_TOKEN]
[--postgres-hostname POSTGRES_HOSTNAME] [--postgres-port POSTGRES_PORT]
[--postgres-username POSTGRES_USERNAME]
[--postgres-password POSTGRES_PASSWORD]
[--postgres-database POSTGRES_DATABASE]
[--bigquery-project-id BIGQUERY_PROJECT_ID]
Expand All @@ -644,6 +611,8 @@ def test_otava_validate_help_output():

options:
-h, --help show this help message and exit
--config-file CONFIG_FILE
Otava config file path [env var: OTAVA_CONFIG]

Graphite Options:
Options for Graphite configuration
Expand Down