コード例 #1
0
ファイル: describe.py プロジェクト: saranraju90/multik8s
 def Args(parser):
     resource_args.AddSingleResourceArgument(
         parser,
         "organization.developer",
         "Email address of the developer to be described. To get a list of "
         "available developers, run `{parent_command} list`.",
         fallthroughs=[defaults.GCPProductOrganizationFallthrough()])
コード例 #2
0
    def Args(parser):
        help_text = {
            "api":
            "API proxy to be undeployed. Must currently be deployed. To "
            "get a list of available deployed proxies, run "
            "`{{grandparent_command}} deployments list --environment=ENV`.",
            "environment":
            "Environment from which to undeploy the API proxy. To "
            "get a list of available environments, run "
            "`{{grandparent_command}} environments list`.",
            "organization":
            "Apigee organization of the proxy and environment."
        }

        fallthroughs = [
            defaults.GCPProductOrganizationFallthrough(),
            defaults.StaticFallthrough("revision", "auto")
        ]
        resource_args.AddSingleResourceArgument(
            parser,
            "organization.environment.api.revision",
            "API proxy revision to be undeployed and environment from which it "
            "should be removed.\n\n"
            "Revisions can either be a positive revision number, or the special "
            "value ``auto'', which will undeploy whatever revision is currently "
            "deployed. If revision is unspecified, the default is ``auto''.",
            fallthroughs=fallthroughs,
            help_texts=help_text)
コード例 #3
0
ファイル: describe.py プロジェクト: saranraju90/multik8s
  def Args(parser):
    help_text = {
        "api": "Deployed API proxy.",
        "environment": "Environment in which the proxy was deployed.",
        "organization": ("Apigee Organization of the proxy and environment. If "
                         "unspecified, the Cloud Platform project's associated "
                         "organization will be used."),
    }
    fallthroughs = [
        defaults.GCPProductOrganizationFallthrough(),
        defaults.StaticFallthrough("revision", "auto")
    ]
    resource_args.AddSingleResourceArgument(
        parser,
        "organization.environment.api.revision",
        """\
API proxy revision and environment of the deployment to be described.


To get a list of deployed proxies and their environments, run:

    $ {parent_command} list

REVISION can either be a positive revision number, or the special value
``auto'', which will choose whichever revision of API is currently deployed in
ENVIRONMENT, or return an error if more than one revision is deployed.


If REVISION is unspecified, the default is ``auto''.

""",
        fallthroughs=fallthroughs,
        help_texts=help_text)
コード例 #4
0
ファイル: deploy.py プロジェクト: bopopescu/gcloud_cli
    def Args(parser):
        parser.add_argument(
            "--override",
            action="store_true",
            help=
            ("Whether to force the deployment of the new revision over the " +
             "currently deployed revision by overriding conflict checks.\n\n" +
             "If an existing API proxy revision is deployed, set this flag " +
             "to ensure seamless deployment with zero downtime. In this " +
             "case, the existing revision remains deployed until the new " +
             "revision is fully deployed. If not set, you must undeploy " +
             "the currently deployed revision before deploying the new " +
             "revision."))

        help_text = {
            "api": "The API proxy to be deployed.",
            "environment": "The environment in which to deploy the API proxy.",
            "organization":
            "The Apigee organization of the proxy and environment."
        }
        fallthroughs = [
            defaults.GCPProductOrganizationFallthrough(),
            defaults.StaticFallthrough("revision", "latest")
        ]
        resource_args.AddSingleResourceArgument(
            parser,
            "organization.environment.api.revision",
            "The API proxy revision to be deployed, and the environment in which "
            "to deploy it. The revision defaults to `latest`, a special value "
            "which will use the latest revision of the API proxy.",
            fallthroughs=fallthroughs,
            help_texts=help_text)
コード例 #5
0
ファイル: list.py プロジェクト: PrateekKhatri/gcloud_cli
 def Args(parser):
     resource_args.AddSingleResourceArgument(
         parser,
         "organization.environment",
         "Apigee environment whose archive deployments should be listed.",
         positional=False,
         required=True,
         fallthroughs=[defaults.GCPProductOrganizationFallthrough()])
     # The response is a JSON array of archive deployment descriptors, so the
     # array needs to be flattened to display as a table.
     parser.display_info.AddFlatten(["archiveDeployments[]"])
     # Cloud SDK projections can be used to format each column of the display
     # table:
     # https://cloud.google.com/sdk/gcloud/reference/topic/projections
     # The "ARCHIVE ID" column scopes the resource path in the "name" field of
     # the API response to only show the id of the archive deployment.
     archive_id_col = ("archiveDeployments.name.scope(archiveDeployments)"
                       ":label='ARCHIVE ID'")
     # The "ENVIORNMENT" column scopes the resource path in the "name" field of
     # the API response to only show the Apigee environment id.
     env_id_col = ("archiveDeployments.name.scope(environments).segment(0)"
                   ":label=ENVIRONMENT")
     # The "CREATED AT" column formats the posix epoch in the "createdAt" field
     # of the API response into a human-readable date format.
     created_col = ("archiveDeployments.createdAt.date("
                    "format='%Y-%m-%d %H:%M:%S %Z', unit=1000000, tz=LOCAL)"
                    ":label='DEPLOYED AT'")
     # The labels field is a list of key/value pairs so it is flattened to
     # display in the table.
     labels_col = "archiveDeployments.labels.flatten()"
     cols = ", ".join([archive_id_col, env_id_col, created_col, labels_col])
     # Format the column definitions into a table.
     table_fmt = "table({})".format(cols)
     parser.display_info.AddFormat(table_fmt)
コード例 #6
0
 def Args(parser):
     resource_args.AddSingleResourceArgument(
         parser,
         "organization.operation",
         "Operation to be described. To get a list of available operations, run "
         "`{{parent_command}} list`.",
         fallthroughs=[defaults.GCPProductOrganizationFallthrough()])
コード例 #7
0
 def Args(parser):
     resource_args.AddSingleResourceArgument(
         parser,
         "organization",
         "The Apigee organization whose deployments should be listed.",
         fallthroughs=[defaults.GCPProductOrganizationFallthrough()])
     parser.display_info.AddFormat("list")
コード例 #8
0
ファイル: describe.py プロジェクト: saranraju90/multik8s
 def Args(parser):
     resource_args.AddSingleResourceArgument(
         parser,
         "organization.app",
         "Application to be described. To get a list of available applications, "
         "run `{parent_command} list`.",
         argument_name="APPLICATION",
         fallthroughs=[defaults.GCPProductOrganizationFallthrough()])
コード例 #9
0
 def Args(parser):
     resource_args.AddSingleResourceArgument(
         parser,
         "organization.environment",
         "Apigee environment to be described. To get a list of available "
         "environments, run `{parent_command} list`.",
         required=True,
         fallthroughs=[defaults.GCPProductOrganizationFallthrough()])
コード例 #10
0
ファイル: describe.py プロジェクト: saranraju90/multik8s
 def Args(parser):
     resource_args.AddSingleResourceArgument(
         parser,
         "organization.product",
         "API product to be described. To get a list of available API products, "
         "run:\n\n\n"
         "    $ {parent_command} list\n\n",
         fallthroughs=[defaults.GCPProductOrganizationFallthrough()])
コード例 #11
0
ファイル: defaults_test.py プロジェクト: bopopescu/gcloud_cli
 def testFallthroughRequiresImplementation(self):
     parser = util.ArgumentParser()
     resource_args.AddSingleResourceArgument(
         parser,
         "organization",
         "The Apigee organization that will test fallback logic.",
         fallthroughs=[BrokenFallthrough()])
     with self.assertRaises(NotImplementedError):
         parser.parse_args([]).CONCEPTS.organization.Parse()
コード例 #12
0
 def testResourceArgumentValidationUnneeded(self):
     parser = util.ArgumentParser()
     resource_args.AddSingleResourceArgument(
         parser, "organization.developer.app",
         "The application that will test name validation logic.")
     weird_name = "\0invalid/nonsense"
     unparsed_args = ["--organization=oo", "--developer=" + weird_name, "a"]
     args = parser.parse_args(unparsed_args).CONCEPTS.app.Parse()
     self.assertEqual(args.developersId, weird_name)
コード例 #13
0
ファイル: list.py プロジェクト: bopopescu/gcloud_cli
 def Args(parser):
     resource_args.AddSingleResourceArgument(
         parser,
         "organization",
         "The Apigee organization whose environments should be listed.",
         positional=False,
         required=True,
         fallthroughs=[defaults.GCPProductOrganizationFallthrough()])
     parser.display_info.AddFormat("list")
コード例 #14
0
 def Args(parser):
     parser.add_argument(
         "--verbose",
         action="store_true",
         help="Include proxy revision info in the description.")
     resource_args.AddSingleResourceArgument(
         parser,
         "organization.api",
         "The API proxy to be described.",
         fallthroughs=[defaults.GCPProductOrganizationFallthrough()])
コード例 #15
0
ファイル: describe.py プロジェクト: PrateekKhatri/gcloud_cli
 def Args(parser):
     resource_args.AddSingleResourceArgument(
         parser,
         "organization.environment.archive_deployment",
         help_text="Archive deployment to be described. To get a list of "
         "available archive deployments, run `{parent_command} list`.",
         argument_name="archive_deployment",
         positional=True,
         required=True,
         fallthroughs=[defaults.GCPProductOrganizationFallthrough()])
コード例 #16
0
 def testResourceArgumentValidationFails(self):
     parser = util.ArgumentParser()
     resource_args.AddSingleResourceArgument(
         parser,
         "organization",
         "The Apigee organization that will test name validation logic.",
         validate=True)
     with self.assertRaises(cli_test_base.MockArgumentError):
         parser.parse_args(["invalid*org*name"
                            ]).CONCEPTS.organization.Parse()
コード例 #17
0
 def testResourceArgumentValidationSucceeds(self):
     parser = util.ArgumentParser()
     resource_args.AddSingleResourceArgument(
         parser,
         "organization",
         "The Apigee organization that will test name validation logic.",
         validate=True)
     args = parser.parse_args(["valid-org1-name1"
                               ]).CONCEPTS.organization.Parse()
     self.assertEqual(args.organizationsId, "valid-org1-name1")
コード例 #18
0
 def testResourceArgumentValidationDisabled(self):
     parser = util.ArgumentParser()
     resource_args.AddSingleResourceArgument(
         parser,
         "organization",
         "The Apigee organization that will test name validation logic.",
         validate=False)
     args = parser.parse_args(["invalid*org*name"
                               ]).CONCEPTS.organization.Parse()
     self.assertEqual(args.organizationsId, "invalid*org*name")
コード例 #19
0
ファイル: list.py プロジェクト: saranraju90/multik8s
 def Args(parser):
   resource_args.AddSingleResourceArgument(
       parser,
       "organization",
       "Apigee organization whose products should be listed. If unspecified, "
       "the Cloud Platform project's associated organization will be used.",
       positional=False,
       required=True,
       fallthroughs=[defaults.GCPProductOrganizationFallthrough()])
   parser.display_info.AddFormat("list(name)")
コード例 #20
0
ファイル: list.py プロジェクト: saranraju90/multik8s
    def Args(parser):
        help_text = {
            "api": ("The API proxy whose deployments should be listed. If not "
                    "provided, all proxies will be listed. To get a list of "
                    "existing API proxies, run "
                    "`{{grandparent_command}} apis list`."),
            "environment":
            ("The environment whose deployments should be listed. "
             "If not provided, all environments will be listed. "
             "To get a list of available environments, run "
             "`{{grandparent_command}} environments list`."),
            "organization":
            ("The organization whose deployments should be listed."
             "If unspecified, the Cloud Platform project's "
             "associated organization will be used."),
        }

        # When Calliope parses a resource's resource arguments, it interprets them
        # as an all-or-nothing whole; if any of them are not provided the whole
        # resource defaults to None.
        #
        # Thus, to make individual parts of the search path optional for the user
        # while accepting others, fallthrough logic for those arguments must be
        # present to return a placeholder value that can be recognized after parsing
        # and interpreted as "no value provided".
        #
        # Unfortunately, `None` won't work as the placeholder, because a fallthrough
        # class returning "None" means it was unable to provide a value at all.
        # Thus, some other value must be chosen.
        fallthroughs = [
            defaults.GCPProductOrganizationFallthrough(),
            # For `revision`, the placeholder MUST be a string, because gcloud
            # concepts will try to parse it as a URL or fully qualified path, and
            # will choke on non-string values. This should be safe as all legitimate
            # revisions are numeric.
            defaults.StaticFallthrough("revision", "all"),
            # For other arguments, the placeholder must not be a string; any string
            # provided here might collide with a real environment or API name. Use
            # the Python builtin function all() as a convenient, idiomatic
            # alternative.
            defaults.StaticFallthrough("environment", all),
            defaults.StaticFallthrough("api", all),
        ]
        resource_args.AddSingleResourceArgument(
            parser,
            "organization.environment.api.revision",
            "API proxy revision and environment whose deployments should be "
            "listed. Providing a REVISION is only valid if API is also specified. "
            "If no REVISION is provided, all deployed revisions that match the "
            "other arguments will be included.",
            positional=False,
            required=True,
            fallthroughs=fallthroughs,
            help_texts=help_text)
        parser.display_info.AddFormat("table(environment,apiProxy,revision)")
コード例 #21
0
ファイル: describe.py プロジェクト: saranraju90/multik8s
 def Args(parser):
     parser.add_argument(
         "--verbose",
         action="store_true",
         help="Include proxy revision info in the description.")
     resource_args.AddSingleResourceArgument(
         parser,
         "organization.api",
         "API proxy to be described. To get a list of available API proxies, "
         "run `{parent_command} list`.",
         fallthroughs=[defaults.GCPProductOrganizationFallthrough()])
コード例 #22
0
 def Args(parser):
     resource_args.AddSingleResourceArgument(
         parser,
         "organization",
         "Organization whose operations should be listed. If unspecified, the "
         "Cloud Platform project's associated organization will be used.",
         positional=False,
         required=True,
         fallthroughs=[defaults.GCPProductOrganizationFallthrough()])
     parser.display_info.AddFormat(
         "table(uuid, organization, metadata.state)")
コード例 #23
0
ファイル: update.py プロジェクト: PrateekKhatri/gcloud_cli
 def Args(parser):
     resource_args.AddSingleResourceArgument(
         parser,
         "organization.environment.archive_deployment",
         help_text="Archive deployment to update. To get a list of "
         "existing archive deployments, run `{parent_command} list`.",
         argument_name="archive_deployment",
         positional=True,
         required=True,
         fallthroughs=[defaults.GCPProductOrganizationFallthrough()])
     # This adds the --update-labels, --remove-labels and --clear-labels flags.
     labels_util.AddUpdateLabelsFlags(parser)
コード例 #24
0
 def Args(parser):
   help_text = {
       "api": "The API proxy to be undeployed.",
       "environment": "The environment from which to undeploy the API proxy.",
       "organization": "The organization of the proxy and environment."
   }
   fallthroughs = [defaults.GCPProductOrganizationFallthrough(),
                   defaults.StaticFallthrough("revision", "auto")]
   resource_args.AddSingleResourceArgument(
       parser, "organization.environment.api.revision",
       "The API proxy revision to be undeployed, and the environment from "
       "which it should be removed. The revision defaults to `auto`, which "
       "will undeploy whichever revision is currently deployed, unless there "
       "is more than one such revision.",
       fallthroughs=fallthroughs, help_texts=help_text)
コード例 #25
0
ファイル: list.py プロジェクト: saranraju90/multik8s
 def Args(parser):
     fallthroughs = [
         defaults.GCPProductOrganizationFallthrough(),
         defaults.StaticFallthrough("developer", ANY_DEVELOPER)
     ]
     resource_args.AddSingleResourceArgument(
         parser,
         "organization.developer",
         "Apigee organization, and optionally developer, whose applications "
         "should be listed. If developer is not specified, all developers will "
         "be listed.\n\n"
         "To get a list of valid developers, run:\n\n"
         "    $ {grandparent_command} developers list\n\n",
         positional=False,
         fallthroughs=fallthroughs)
     parser.display_info.AddFormat("table(appId, name)")
コード例 #26
0
ファイル: list.py プロジェクト: bopopescu/gcloud_cli
    def Args(parser):
        help_text = {
            "api": "The API proxy whose deployments should be listed.",
            "environment":
            "The environment whose deployments should be listed. "
            "If not provided, all environments will be listed.",
            "organization":
            "The organization whose deployments should be listed."
        }

        # `api` is a required argument for this command, but `environment` and
        # `revision` are not. In order to make `api` required, the whole resource
        # argument has to be "required" from gcloud concepts's point of view.
        #
        # Thus, to make `environment` and `revision` optional for the user, they
        # must be given fallthrough logic that fills in a placeholder value; this
        # value can then be recognized after parsing and interpreted as "no value
        # provided".
        #
        # Unfortunately, `None` won't work as the placeholder, because a fallthrough
        # class returning "None" means it was unable to provide a value at all.
        # Thus, some other value must be chosen.
        fallthroughs = [
            defaults.GCPProductOrganizationFallthrough(),
            # For `environment`, the placeholder must not be a string; any string
            # provided here might collide with a real environment name. Use the
            # Python builtin function all() as a convenient, idiomatic alternative.
            defaults.StaticFallthrough("environment", all),
            # For `revision`, the placeholder MUST be a string, because gcloud
            # concepts will try to parse it as a URL or fully qualified path, and
            # will choke on non-string values. This should be safe as all legitimate
            # revisions are numeric.
            defaults.StaticFallthrough("revision", "all")
        ]
        resource_args.AddSingleResourceArgument(
            parser,
            "organization.environment.api.revision",
            "The API proxy revision whose deployments should be listed. If a "
            "`--revision` is not provided, all revisions will be listed.",
            positional=False,
            required=True,
            fallthroughs=fallthroughs,
            help_texts=help_text)
        parser.display_info.AddFormat("list")
コード例 #27
0
ファイル: describe.py プロジェクト: bopopescu/gcloud_cli
 def Args(parser):
     help_text = {
         "api": "The deployed API proxy.",
         "environment": "The environment in which the proxy was deployed.",
         "organization": "The organization of the proxy and environment."
     }
     fallthroughs = [
         defaults.GCPProductOrganizationFallthrough(),
         defaults.StaticFallthrough("revision", "auto")
     ]
     resource_args.AddSingleResourceArgument(
         parser,
         "organization.environment.api.revision",
         "The API proxy revision and environment of the deployment to be "
         "described. `REVISION` defaults to ``auto'', which will describe "
         "whichever revision is currently deployed. However, if more than one "
         "revision of `API` is deployed in `ENVIRONMENT`, then an explicit "
         "`REVISION` is required or the command will fail.",
         fallthroughs=fallthroughs,
         help_texts=help_text)
コード例 #28
0
 def Args(parser):
     fallthroughs = [defaults.GCPProductOrganizationFallthrough()]
     resource_args.AddSingleResourceArgument(
         parser,
         resource_path="organization.environment",
         help_text=("Apigee environment in which to deploy the archive "
                    "deployment."),
         fallthroughs=fallthroughs,
         positional=False,
         required=True)
     # Create a argument group to manage that only one of either --source or
     # --bundle-file flags are provided on the command line.
     source_input_group = parser.add_group(mutex=True, help="Source input.")
     source_input_group.add_argument(
         "--source",
         required=False,
         type=files.ExpandHomeDir,
         help="The source directory of the archive to upload.")
     source_input_group.add_argument(
         "--bundle-file",
         required=False,
         type=files.ExpandHomeDir,
         help="The zip file containing an archive to upload.")
     parser.add_argument(
         "--async",
         action="store_true",
         dest="async_",
         help=(
             "If set, returns immediately and outputs a description of the "
             "long running operation that was launched. Else, `{command}` "
             "will block until the archive deployment has been successfully "
             "deployed to the specified environment.\n\n"
             "To monitor the operation once it's been launched, run "
             "`{grandparent_command} operations describe OPERATION_NAME`."))
     # This adds the --labels flag.
     labels_util.AddCreateLabelsFlags(parser)
コード例 #29
0
 def Args(parser):
     fallthroughs = [defaults.GCPProductOrganizationFallthrough()]
     resource_args.AddSingleResourceArgument(
         parser,
         resource_path="organization.environment",
         help_text=("Apigee environment in which to deploy the archive "
                    "deployment."),
         fallthroughs=fallthroughs,
         positional=False,
         required=True)
     parser.add_argument("--source",
                         required=False,
                         help="The source directory to upload.")
     parser.add_argument(
         "--async",
         action="store_true",
         dest="async_",
         help=(
             "If set, returns immediately and outputs a description of the "
             "long running operation that was launched. Else, `{command}` "
             "will block until the archive deployment has been successfully "
             "deployed to the specified environment.\n\n"
             "To monitor the operation once it's been launched, run "
             "`{grandparent_command} operations describe OPERATION_NAME`."))
コード例 #30
0
ファイル: create.py プロジェクト: saranraju90/multik8s
  def Args(parser):
    # Can't use fallthroughs for optional resource arguments, as they won't run
    # unless at least one argument from the set is provided.
    resource_args.AddSingleResourceArgument(
        parser,
        "organization.product",
        "API product to be created. Characters in a product's internal name "
        "are restricted to: ```A-Za-z0-9._-$ %```.",
        validate=True,
        argument_name="INTERNAL_NAME",
        required=False)

    environment_group = parser.add_mutually_exclusive_group()

    environment_group.add_argument(
        "--environments",
        metavar="ENVIRONMENT",
        type=arg_parsers.ArgList(min_length=1),
        help=("Environments to which the API product is bound. Requests to "
              "environments that are not listed are rejected, preventing "
              "developers from accessing those resources through API Proxies "
              "deployed in another environment.\n\n"
              "For example, this can prevent resources associated with API "
              "proxies in a ``prod'' environment from also granting access to "
              "matching API proxies deployed in a ``test'' environment.\n\n"
              "To get a list of available environments, run:\n\n"
              "    $ {grandparent_command} environments list"))

    environment_group.add_argument(
        "--all-environments",
        dest="environments",
        action="store_const",
        const=[],
        help="Make all environments accessible through this API product.")

    parser.add_argument(
        "--display-name",
        help=("Name to be displayed in the UI or developer portal to "
              "developers registering for API access."))

    access_group = parser.add_mutually_exclusive_group()
    access_group.add_argument(
        "--public-access",
        dest="access",
        action="store_const",
        const="public",
        help=("Make this API product visible to developers in the Apigee "
              "developer portal."))
    access_group.add_argument(
        "--private-access",
        dest="access",
        action="store_const",
        const="private",
        help=("Hide this API product in the developer portal but make it "
              "accessible by external developers."))
    access_group.add_argument(
        "--internal-access",
        dest="access",
        action="store_const",
        const="internal",
        help="Prevent external access to this API product.")

    proxies_mutex_group = parser.add_mutually_exclusive_group(
        "Arguments specifying which API proxies and resources to expose.")

    proxies_mutex_group.add_argument(
        "--all-proxies",
        action="store_true",
        help=("Expose all available API proxies and their resources. Must be "
              "explicitly specified if neither `--apis` nor `--resources` is "
              "provided."))

    proxies_group = proxies_mutex_group.add_argument_group(
        "Arguments that restrict exposed API proxies. One or both of these may "
        "be specified if `--all-proxies` is not:")

    proxies_group.add_argument(
        "--apis",
        metavar="API",
        type=arg_parsers.ArgList(),
        help="""\
Comma-separated names of API proxies to which this API product is bound. Only
those API proxies will be accessible through the new API product.

If not provided, all deployed API proxies will be included in the product, so
long as they match the other parameters.

The API proxy names must already be deployed to the bound environments, or
creation of the API product will fail. To get a list of deployed API proxies,
run:

    $ {grandparent_command} deployments list

To deploy an API proxy, run:

    $ {grandparent_command} apis deploy""")

    # Resource paths conform to RFC 2396's segment format, so a "," may appear
    # in one, but a "#" will not. " " or "|" would also have worked, but would
    # have been harder to read in help text; spaces and pipes have special
    # meaning in usage strings.
    proxies_group.add_argument(
        "--resources",
        metavar="RESOURCE",
        type=argument_groups.HashDelimitedArgList(min_length=1),
        help="""\
API resources to be bundled in the API product, separated by `#` signs.

By default, the resource paths are mapped from the `proxy.pathsuffix` variable.

The proxy path suffix is defined as the URI fragment following the
ProxyEndpoint base path. For example, if ``/forecastrss'' is given as an element
of this list, and the base path defined for the API proxy is `/weather`, then
only requests to `/weather/forecastrss` are permitted by the API product.

Proxy paths can use asterisks as wildcards; `/**` indicates that all sub-URIs
are included, whereas a single asterisk indicates that only URIs one level
down are included.

By default, `/` supports the same resources as `/**` as well as the base path
defined by the API proxy.

For example, if the base path of the API proxy is `/v1/weatherapikey`, then
the API product supports requests to `/v1/weatherapikey` and to any sub-URIs,
such as `/v1/weatherapikey/forecastrss`, `/v1/weatherapikey/region/CA`, and so
on.

If not provided, all deployed API resources will be included in the product, so
long as they match the other parameters.

The API proxy resources must already be deployed to the bound environments, or
creation of the API product will fail.""")

    quota_group = parser.add_argument_group(
        ("To impose a quota limit on calls to the API product, specify all of "
         "the following:"))

    quota_group.add_argument(
        "--quota",
        type=int,
        help="""Number of request messages permitted per app by this API product
for the specified `--quota-interval` and `--quota-unit`.

For example, to create an API product that allows 50 requests every twelve hours
to every deployed API proxy, run:

    $ {command} PRODUCT --all-environments --all-proxies --public-access --quota=50 --quota-interval=12 --quota-unit=hour

If specified, `--quota-interval` and `--quota-unit` must be specified too.""")
    quota_group.add_argument(
        "--quota-interval",
        type=int,
        help=("Time interval over which the number of request messages is "
              "calculated.\n\n"
              "If specified, `--quota` and `--quota-unit` must be specified "
              "too."))
    quota_group.add_argument(
        "--quota-unit",
        choices=["minute", "hour", "day", "month"],
        help=("Time unit for `--quota-interval`.\n\n"
              "If specified, `--quota` and `--quota-interval` must be "
              "specified too."))

    parser.add_argument(
        "--description",
        help=("Overview of the API product. Include key information about the "
              "API product that is not captured by other fields."))

    parser.add_argument(
        "--manual-approval",
        action="store_true",
        help=("Require manual approval of developer requests to access this "
              "API product before their consumer keys can be used. If unset, "
              "the consumer key is generated in an \"approved\" state and can "
              "be used immediately."))

    parser.add_argument(
        "--oauth-scopes",
        metavar="SCOPE",
        type=arg_parsers.ArgList(),
        help=("Comma-separated list of OAuth scopes that are validated at "
              "runtime. Apigee validates that the scopes in any access token "
              "presented match the scopes defined in the OAuth policy "
              "assoicated with the API product."))

    parser.add_argument(
        "--attributes",
        metavar="NAME=VALUE",
        type=arg_parsers.ArgDict(max_length=17),
        help=("Key-value attribute pairs that may be used to extend the "
              "default API product profile with customer-specific metadata. Up "
              "to 17 attributes can be specified."))