def create_arg_parser()

in esrally/rally.py [0:0]


def create_arg_parser():
    def valid_date(v):
        pattern = "%Y%m%d"
        try:
            datetime.datetime.strptime(v, pattern)
            # don't convert, just check that the format is correct, we'll use the string value later on anyway
            return v
        except ValueError:
            msg = f"[{v}] does not conform to the pattern [yyyyMMdd]"
            raise argparse.ArgumentTypeError(msg)

    def positive_number(v):
        value = int(v)
        if value <= 0:
            raise argparse.ArgumentTypeError(f"must be positive but was {value}")
        return value

    def non_empty_list(arg):
        lst = opts.csv_to_list(arg)
        if len(lst) < 1:
            raise argparse.ArgumentError(argument=None, message="At least one argument required!")
        return lst

    def runtime_jdk(v):
        if v == "bundled":
            return v
        else:
            try:
                return positive_number(v)
            except argparse.ArgumentTypeError:
                raise argparse.ArgumentTypeError(f"must be a positive number or 'bundled' but was {v}")

    def supported_es_version(v):
        if v:
            min_es_version = versions.Version.from_string(version.minimum_es_version())
            specified_version = versions.Version.from_string(v)
            if specified_version < min_es_version:
                raise argparse.ArgumentTypeError(f"must be at least {min_es_version} but was {v}")
        return v

    def revision(v):
        return v.strip()

    def add_track_source(subparser):
        track_source_group = subparser.add_mutually_exclusive_group()
        track_source_group.add_argument(
            "--track-repository",
            help="Define the repository from where Rally will load tracks (default: default).",
            # argparse is smart enough to use this default only if the user did not use --track-path and also did not specify anything
            default="default",
        )
        track_source_group.add_argument(
            "--track-path",
            help="Define the path to a track.",
        )
        subparser.add_argument(
            "--track-revision",
            help="Define a specific revision in the track repository that Rally should use.",
            default=None,
            type=revision,
        )

    # try to preload configurable defaults, but this does not work together with `--configuration-name` (which is undocumented anyway)
    cfg = config.Config()
    if cfg.config_present():
        cfg.load_config()
        preserve_install = cfg.opts("defaults", "preserve_benchmark_candidate", default_value=False, mandatory=False)
    else:
        preserve_install = False

    parser = argparse.ArgumentParser(
        prog=PROGRAM_NAME,
        description=BANNER + "\n\n You Know, for Benchmarking Elasticsearch.",
        epilog=f"Find out more about Rally at {console.format.link(doc_link())}",
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    parser.add_argument(
        "--version",
        action="version",
        version="%(prog)s " + version.version(),
    )

    subparsers = parser.add_subparsers(title="subcommands", dest="subcommand", help="")

    race_parser = subparsers.add_parser("race", help="Run a benchmark")
    # change in favor of "list telemetry", "list tracks", "list pipelines"
    list_parser = subparsers.add_parser("list", help="List configuration options")
    list_parser.add_argument(
        "configuration",
        metavar="configuration",
        help="The configuration for which Rally should show the available options. "
        "Possible values are: telemetry, tracks, pipelines, races, cars, elasticsearch-plugins, annotations",
        choices=["telemetry", "tracks", "pipelines", "races", "cars", "elasticsearch-plugins", "annotations"],
    )
    list_parser.add_argument(
        "--limit",
        help="Limit the number of search results for recent races (default: 10).",
        default=10,
    )
    list_parser.add_argument(
        "--track",
        help="Show only records from this track",
        default=None,
    )
    list_parser.add_argument(
        "--benchmark-name",
        help="Show only records from with corresponding 'name' or 'benchmark-name' user tag",
        default=None,
    )
    list_parser.add_argument(
        "--from-date",
        help="Show only records on or after this date (format: yyyyMMdd)",
        type=valid_date,
        default=None,
    )
    list_parser.add_argument(
        "--to-date",
        help="Show only records before or on this date (format: yyyyMMdd)",
        type=valid_date,
        default=None,
    )
    list_parser.add_argument(
        "--challenge",
        help="Show only records from this challenge",
        default=None,
    )
    add_track_source(list_parser)

    delete_parser = subparsers.add_parser("delete", help="Delete records")
    delete_parser.add_argument(
        "configuration",
        metavar="configuration",
        help="The configuration for which Rally should delete the available records. Possible values are: race, annotation",
        choices=["race", "annotation"],
    )
    delete_parser.add_argument(
        "--dry-run", help="Just show what would be done but do not apply the operation.", default=False, action="store_true"
    )
    delete_parser.add_argument("--id", help="Ids of the items to delete. Separate multiple ids with a comma.", required=True)
    add_track_source(delete_parser)

    info_parser = subparsers.add_parser("info", help="Show info about a track")
    add_track_source(info_parser)
    info_parser.add_argument(
        "--track",
        help=f"Define the track to use. List possible tracks with `{PROGRAM_NAME} list tracks`.",
        # we set the default value later on because we need to determine whether the user has provided this value.
        # default="geonames"
    )

    info_parser.add_argument(
        "--track-params",
        help="Define a comma-separated list of key:value pairs that are injected verbatim to the track as variables.",
        default="",
    )
    info_parser.add_argument(
        "--challenge",
        help=f"Define the challenge to use. List possible challenges for tracks with `{PROGRAM_NAME} list tracks`.",
    )
    info_task_filter_group = info_parser.add_mutually_exclusive_group()
    info_task_filter_group.add_argument(
        "--include-tasks",
        help="Defines a comma-separated list of tasks to run. By default all tasks of a challenge are run.",
    )
    info_task_filter_group.add_argument(
        "--exclude-tasks",
        help="Defines a comma-separated list of tasks not to run. By default all tasks of a challenge are run.",
    )

    create_track_parser = subparsers.add_parser("create-track", help="Create a Rally track from existing data")
    create_track_parser.add_argument(
        "--track",
        required=True,
        help="Name of the generated track",
    )
    create_track_parser.add_argument(
        "--batch-size",
        default=1000,
        help="Number of documents to collect per call to Elasticsearch.",
    )
    indices_or_data_streams_group = create_track_parser.add_mutually_exclusive_group(required=True)
    indices_or_data_streams_group.add_argument(
        "--indices",
        type=non_empty_list,
        help="Comma-separated list of indices to include in the track",
    )
    indices_or_data_streams_group.add_argument(
        "--data-streams",
        type=non_empty_list,
        help="Comma-separated list of data streams to include in the track",
    )
    create_track_parser.add_argument(
        "--target-hosts",
        default="",
        required=True,
        help="Comma-separated list of host:port pairs which should be targeted",
    )
    create_track_parser.add_argument(
        "--client-options",
        default=opts.ClientOptions.DEFAULT_CLIENT_OPTIONS,
        help=f"Comma-separated list of client options to use. (default: {opts.ClientOptions.DEFAULT_CLIENT_OPTIONS})",
    )
    create_track_parser.add_argument(
        "--output-path",
        default=os.path.join(os.getcwd(), "tracks"),
        help="Track output directory (default: tracks/)",
    )

    compare_parser = subparsers.add_parser("compare", help="Compare two races")
    compare_parser.add_argument(
        "--baseline",
        required=True,
        help=f"Race ID of the baseline (see {PROGRAM_NAME} list races).",
    )
    compare_parser.add_argument(
        "--contender",
        required=True,
        help=f"Race ID of the contender (see {PROGRAM_NAME} list races).",
    )
    compare_parser.add_argument(
        "--report-format",
        help="Define the output format for the command line report (default: markdown).",
        choices=["markdown", "csv"],
        default="markdown",
    )
    compare_parser.add_argument(
        "--report-numbers-align",
        help="Define the output column number alignment for the command line report (default: decimal).",
        choices=["right", "center", "left", "decimal"],
        default="decimal",
    )
    compare_parser.add_argument(
        "--report-file",
        help="Write the command line report also to the provided file.",
        default="",
    )
    compare_parser.add_argument(
        "--show-in-report",
        help="Whether to include the comparison in the results file.",
        default=True,
    )

    build_parser = subparsers.add_parser("build", help="Builds an artifact")
    build_parser.add_argument(
        "--revision",
        help="Define the source code revision for building the benchmark candidate. 'current' uses the source tree as is,"
        " 'latest' fetches the latest version on the main branch. It is also possible to specify a commit id or a timestamp."
        ' The timestamp must be specified as: "@ts" where "ts" must be a valid ISO 8601 timestamp, '
        'e.g. "@2013-07-27T10:37:00Z" (default: current). A combination of branch and timestamp is also possible,'
        'e.g. "feature-branch@2023-04-06T14:52:31Z".',
        default="current",
        type=revision,
    )  # optimized for local usage, don't fetch sources
    build_parser.add_argument(
        "--target-os",
        help="The name of the target operating system for which an artifact should be downloaded (default: current OS)",
    )
    build_parser.add_argument(
        "--target-arch",
        help="The name of the CPU architecture for which an artifact should be downloaded (default: current architecture)",
    )
    build_parser.add_argument(
        "--team-repository",
        help="Define the repository from where Rally will load teams and cars (default: default).",
        default="default",
    )
    build_parser.add_argument(
        "--team-revision",
        help="Define a specific revision in the team repository that Rally should use.",
        default=None,
        type=revision,
    )
    build_parser.add_argument(
        "--team-path",
        help="Define the path to the car and plugin configurations to use.",
    )
    build_parser.add_argument(
        "--car",
        help=f"Define the car to use. List possible cars with `{PROGRAM_NAME} list cars` (default: defaults).",
        default="defaults",
    )  # optimized for local usage
    build_parser.add_argument(
        "--car-params",
        help="Define a comma-separated list of key:value pairs that are injected verbatim as variables for the car.",
        default="",
    )
    build_parser.add_argument(
        "--elasticsearch-plugins",
        help="Define the Elasticsearch plugins to install. (default: install no plugins).",
        default="",
    )
    build_parser.add_argument(
        "--plugin-params",
        help="Define a comma-separated list of key:value pairs that are injected verbatim to all plugins as variables.",
        default="",
    )
    build_parser.add_argument(
        "--source-build-method",
        help="Method with which to build Elasticsearch and plugins from source",
        choices=["docker", "default"],
        default="default",
    )

    download_parser = subparsers.add_parser("download", help="Downloads an artifact")
    download_parser.add_argument(
        "--team-repository",
        help="Define the repository from where Rally will load teams and cars (default: default).",
        default="default",
    )
    download_parser.add_argument(
        "--team-revision",
        help="Define a specific revision in the team repository that Rally should use.",
        default=None,
        type=revision,
    )
    download_parser.add_argument(
        "--team-path",
        help="Define the path to the car and plugin configurations to use.",
    )
    download_parser.add_argument(
        "--distribution-version",
        type=supported_es_version,
        help="Define the version of the Elasticsearch distribution to download. "
        "Check https://www.elastic.co/downloads/elasticsearch for released versions.",
        default="",
    )
    download_parser.add_argument(
        "--distribution-repository",
        help="Define the repository from where the Elasticsearch distribution should be downloaded (default: release).",
        default="release",
    )
    download_parser.add_argument(
        "--car",
        help=f"Define the car to use. List possible cars with `{PROGRAM_NAME} list cars` (default: defaults).",
        default="defaults",
    )  # optimized for local usage
    download_parser.add_argument(
        "--car-params",
        help="Define a comma-separated list of key:value pairs that are injected verbatim as variables for the car.",
        default="",
    )
    download_parser.add_argument(
        "--target-os",
        help="The name of the target operating system for which an artifact should be downloaded (default: current OS)",
    )
    download_parser.add_argument(
        "--target-arch",
        help="The name of the CPU architecture for which an artifact should be downloaded (default: current architecture)",
    )

    install_parser = subparsers.add_parser("install", help="Installs an Elasticsearch node locally")
    install_parser.add_argument(
        "--revision",
        help="Define the source code revision for building the benchmark candidate. 'current' uses the source tree as is,"
        " 'latest' fetches the latest version on the main branch. It is also possible to specify a commit id or a timestamp."
        ' The timestamp must be specified as: "@ts" where "ts" must be a valid ISO 8601 timestamp, '
        'e.g. "@2013-07-27T10:37:00Z" (default: current).',
        default="current",
        type=revision,
    )  # optimized for local usage, don't fetch sources
    # Intentionally undocumented as we do not consider Docker a fully supported option.
    install_parser.add_argument(
        "--build-type",
        help=argparse.SUPPRESS,
        choices=["tar", "docker"],
        default="tar",
    )
    install_parser.add_argument(
        "--team-repository",
        help="Define the repository from where Rally will load teams and cars (default: default).",
        default="default",
    )
    install_parser.add_argument(
        "--team-revision",
        help="Define a specific revision in the team repository that Rally should use.",
        default=None,
        type=revision,
    )
    install_parser.add_argument(
        "--team-path",
        help="Define the path to the car and plugin configurations to use.",
    )
    install_parser.add_argument(
        "--runtime-jdk",
        type=runtime_jdk,
        help="The major version of the runtime JDK to use during installation.",
        default=None,
    )
    install_parser.add_argument(
        "--distribution-repository",
        help="Define the repository from where the Elasticsearch distribution should be downloaded (default: release).",
        default="release",
    )
    install_parser.add_argument(
        "--distribution-version",
        type=supported_es_version,
        help="Define the version of the Elasticsearch distribution to download. "
        "Check https://www.elastic.co/downloads/elasticsearch for released versions.",
        default="",
    )
    install_parser.add_argument(
        "--car",
        help=f"Define the car to use. List possible cars with `{PROGRAM_NAME} list cars` (default: defaults).",
        default="defaults",
    )  # optimized for local usage
    install_parser.add_argument(
        "--car-params",
        help="Define a comma-separated list of key:value pairs that are injected verbatim as variables for the car.",
        default="",
    )
    install_parser.add_argument(
        "--elasticsearch-plugins",
        help="Define the Elasticsearch plugins to install. (default: install no plugins).",
        default="",
    )
    install_parser.add_argument(
        "--plugin-params",
        help="Define a comma-separated list of key:value pairs that are injected verbatim to all plugins as variables.",
        default="",
    )
    install_parser.add_argument(
        "--network-host",
        help="The IP address to bind to and publish",
        default="127.0.0.1",
    )
    install_parser.add_argument(
        "--http-port",
        help="The port to expose for HTTP traffic",
        default="39200",
    )
    install_parser.add_argument(
        "--node-name",
        help="The name of this Elasticsearch node",
        default="rally-node-0",
    )
    install_parser.add_argument(
        "--master-nodes",
        help="A comma-separated list of the initial master node names",
        default="",
    )
    install_parser.add_argument(
        "--seed-hosts",
        help="A comma-separated list of the initial seed host IPs",
        default="",
    )
    install_parser.add_argument(
        "--source-build-method",
        help="Method with which to build Elasticsearch and plugins from source",
        choices=["docker", "default"],
        default="default",
    )
    install_parser.add_argument(
        "--installation-id",
        required=False,
        help="The id to use for the installation",
        default=str(uuid.uuid4()),
    )
    for p in [race_parser, install_parser]:
        p.add_argument(
            "--cluster-name",
            help="The name of this Elasticsearch cluster",
            default="rally-benchmark",
        )

    start_parser = subparsers.add_parser("start", help="Starts an Elasticsearch node locally")
    start_parser.add_argument(
        "--installation-id",
        required=True,
        help="The id of the installation to start",
        # the default will be dynamically derived by racecontrol based on the presence / absence of other command line options
        default="",
    )
    start_parser.add_argument(
        "--race-id",
        required=True,
        help="Define a unique id for this race.",
        default="",
    )
    start_parser.add_argument(
        "--runtime-jdk",
        type=runtime_jdk,
        help="The major version of the runtime JDK to use.",
        default=None,
    )
    start_parser.add_argument(
        "--telemetry",
        help=f"Enable the provided telemetry devices, provided as a comma-separated list. List possible telemetry "
        f"devices with `{PROGRAM_NAME} list telemetry`.",
        default="",
    )
    start_parser.add_argument(
        "--telemetry-params",
        help="Define a comma-separated list of key:value pairs that are injected verbatim to the telemetry devices as parameters.",
        default="",
    )

    stop_parser = subparsers.add_parser("stop", help="Stops an Elasticsearch node locally")
    stop_parser.add_argument(
        "--installation-id",
        required=True,
        help="The id of the installation to stop",
        # the default will be dynamically derived by racecontrol based on the presence / absence of other command line options
        default="",
    )
    stop_parser.add_argument(
        "--preserve-install",
        help=f"Keep the benchmark candidate and its index. (default: {str(preserve_install).lower()}).",
        default=preserve_install,
        action="store_true",
    )

    for p in [list_parser, race_parser]:
        p.add_argument(
            "--distribution-version",
            type=supported_es_version,
            help="Define the version of the Elasticsearch distribution to download. "
            "Check https://www.elastic.co/downloads/elasticsearch for released versions.",
            default="",
        )
        p.add_argument(
            "--team-path",
            help="Define the path to the car and plugin configurations to use.",
        )
        p.add_argument(
            "--team-repository",
            help="Define the repository from where Rally will load teams and cars (default: default).",
            default="default",
        )
        p.add_argument(
            "--team-revision",
            help="Define a specific revision in the team repository that Rally should use.",
            default=None,
            type=revision,
        )

    race_parser.add_argument(
        "--race-id",
        help="Define a unique id for this race.",
        default=str(uuid.uuid4()),
    )
    race_parser.add_argument(
        "--pipeline",
        help="Select the pipeline to run.",
        # the default will be dynamically derived by racecontrol based on the presence / absence of other command line options
        default="",
    )
    race_parser.add_argument(
        "--revision",
        help="Define the source code revision for building the benchmark candidate. 'current' uses the source tree as is,"
        " 'latest' fetches the latest version on master. It is also possible to specify a commit id or a timestamp."
        ' The timestamp must be specified as: "@ts" where "ts" must be a valid ISO 8601 timestamp, '
        'e.g. "@2013-07-27T10:37:00Z" (default: current).',
        default="current",
        type=revision,
    )  # optimized for local usage, don't fetch sources
    add_track_source(race_parser)
    race_parser.add_argument(
        "--track",
        help=f"Define the track to use. List possible tracks with `{PROGRAM_NAME} list tracks`.",
    )
    race_parser.add_argument(
        "--track-params",
        help="Define a comma-separated list of key:value pairs that are injected verbatim to the track as variables.",
        default="",
    )
    race_parser.add_argument(
        "--challenge",
        help=f"Define the challenge to use. List possible challenges for tracks with `{PROGRAM_NAME} list tracks`.",
    )
    race_parser.add_argument(
        "--car",
        help=f"Define the car to use. List possible cars with `{PROGRAM_NAME} list cars` (default: defaults).",
        default="defaults",
    )  # optimized for local usage
    race_parser.add_argument(
        "--car-params",
        help="Define a comma-separated list of key:value pairs that are injected verbatim as variables for the car.",
        default="",
    )
    race_parser.add_argument(
        "--runtime-jdk",
        type=runtime_jdk,
        help="The major version of the runtime JDK to use.",
        default=None,
    )
    race_parser.add_argument(
        "--elasticsearch-plugins",
        help="Define the Elasticsearch plugins to install. (default: install no plugins).",
        default="",
    )
    race_parser.add_argument(
        "--plugin-params",
        help="Define a comma-separated list of key:value pairs that are injected verbatim to all plugins as variables.",
        default="",
    )
    race_parser.add_argument(
        "--target-hosts",
        help="Define a comma-separated list of host:port pairs which should be targeted if using the pipeline 'benchmark-only' "
        "(default: localhost:9200).",
        default="",
    )  # actually the default is pipeline specific and it is set later
    race_parser.add_argument(
        "--load-driver-hosts",
        help="Define a comma-separated list of hosts which should generate load (default: localhost).",
        default="localhost",
    )
    race_parser.add_argument(
        "--client-options",
        help=f"Define a comma-separated list of client options to use. The options will be passed to the Elasticsearch "
        f"Python client (default: {opts.ClientOptions.DEFAULT_CLIENT_OPTIONS}).",
        default=opts.ClientOptions.DEFAULT_CLIENT_OPTIONS,
    )
    race_parser.add_argument(
        "--on-error",
        choices=["continue", "abort"],
        help="Controls how Rally behaves on response errors (default: continue).",
        default="continue",
    )
    race_parser.add_argument(
        "--telemetry",
        help=f"Enable the provided telemetry devices, provided as a comma-separated list. List possible telemetry "
        f"devices with `{PROGRAM_NAME} list telemetry`.",
        default="",
    )
    race_parser.add_argument(
        "--telemetry-params",
        help="Define a comma-separated list of key:value pairs that are injected verbatim to the telemetry devices as parameters.",
        default="",
    )
    race_parser.add_argument(
        "--distribution-repository",
        help="Define the repository from where the Elasticsearch distribution should be downloaded (default: release).",
        default="release",
    )

    task_filter_group = race_parser.add_mutually_exclusive_group()
    task_filter_group.add_argument(
        "--include-tasks",
        help="Defines a comma-separated list of tasks to run. By default all tasks of a challenge are run.",
    )
    task_filter_group.add_argument(
        "--exclude-tasks",
        help="Defines a comma-separated list of tasks not to run. By default all tasks of a challenge are run.",
    )
    race_parser.add_argument(
        "--user-tag",
        "--user-tags",
        help="Define a user-specific key-value pair (separated by ':'). It is added to each metric record as meta info. "
        "Example: intention:baseline-ticket-12345",
        default="",
    )
    race_parser.add_argument(
        "--report-format",
        help="Define the output format for the command line report (default: markdown).",
        choices=["markdown", "csv"],
        default="markdown",
    )
    race_parser.add_argument(
        "--report-numbers-align",
        help="Define the output column number alignment for the command line report (default: decimal).",
        choices=["right", "center", "left", "decimal"],
        default="decimal",
    )
    race_parser.add_argument(
        "--show-in-report",
        help="Define which values are shown in the summary report (default: available).",
        choices=["available", "all-percentiles", "all"],
        default="available",
    )
    race_parser.add_argument(
        "--report-file",
        help="Write the command line report also to the provided file.",
        default="",
    )
    race_parser.add_argument(
        "--preserve-install",
        help=f"Keep the benchmark candidate and its index. (default: {str(preserve_install).lower()}).",
        default=preserve_install,
        action="store_true",
    )
    race_parser.add_argument(
        "--test-mode",
        help="Runs the given track in 'test mode'. Meant to check a track for errors but not for real benchmarks (default: false).",
        default=False,
        action="store_true",
    )
    race_parser.add_argument(
        "--enable-driver-profiling",
        help="Enables a profiler for analyzing the performance of calls in Rally's driver (default: false).",
        default=False,
        action="store_true",
    )
    race_parser.add_argument(
        "--enable-assertions",
        help="Enables assertion checks for tasks (default: false).",
        default=False,
        action="store_true",
    )
    race_parser.add_argument(
        "--kill-running-processes",
        action="store_true",
        default=False,
        help="If any processes is running, it is going to kill them and allow Rally to continue to run.",
    )
    race_parser.add_argument(
        "--source-build-method",
        help="Method with which to build Elasticsearch and plugins from source",
        choices=["docker", "default"],
        default="default",
    )

    ###############################################################################
    #
    # The options below are undocumented and can be removed or changed at any time.
    #
    ###############################################################################
    # This option is intended to tell Rally to assume a different start date than 'now'. This is effectively just useful for things like
    # backtesting or a benchmark run across environments (think: comparison of EC2 and bare metal) but never for the typical user.
    race_parser.add_argument(
        "--effective-start-date",
        help=argparse.SUPPRESS,
        type=lambda s: datetime.datetime.strptime(s, "%Y-%m-%d %H:%M:%S"),
        default=None,
    )
    # Skips checking that the REST API is available before proceeding with the benchmark
    race_parser.add_argument(
        "--skip-rest-api-check",
        help=argparse.SUPPRESS,
        action="store_true",
        default=False,
    )

    add_parser = subparsers.add_parser("add", help="Add records")
    add_parser.add_argument(
        "configuration",
        metavar="configuration",
        help="The configuration for which Rally should add records. " "Possible values are: annotation",
        choices=["annotation"],
    )
    add_parser.add_argument(
        "--dry-run", help="Just show what would be done but do not apply the operation.", default=False, action="store_true"
    )
    add_parser.add_argument("--race-timestamp", help="Race timestamp", required=True)
    add_parser.add_argument("--track", help="Track. If none given, applies to all tracks", default=None)
    add_parser.add_argument(
        "--chart-type",
        help="Chart type to target. If none given, applies to all charts.",
        choices=[
            "query",
            "script",
            "stats",
            "indexing",
            "gc",
            "index_times",
            "merge_times",
            "merge_count",
            "refresh_times",
            "segment_count",
            "io",
            "ml_processing_time",
        ],
        default=None,
    )
    add_parser.add_argument("--chart-name", help="A chart name to target. If none given, applies to all charts.", default=None)
    add_parser.add_argument("--message", help="Annotation message", required=True)

    for p in [
        list_parser,
        delete_parser,
        add_parser,
        race_parser,
        compare_parser,
        build_parser,
        download_parser,
        install_parser,
        start_parser,
        stop_parser,
        info_parser,
        create_track_parser,
    ]:
        # This option is needed to support a separate configuration for the integration tests on the same machine
        p.add_argument(
            "--configuration-name",
            help=argparse.SUPPRESS,
            default=None,
        )
        p.add_argument(
            "--quiet",
            help="Suppress as much as output as possible (default: false).",
            default=False,
            action="store_true",
        )
        p.add_argument(
            "--offline",
            help="Assume that Rally has no connection to the Internet (default: false).",
            default=False,
            action="store_true",
        )

    return parser