From 88b7ac79f0bb9d9b81da48f21f5780169c60fe5f Mon Sep 17 00:00:00 2001 From: OCI DEX Release Bot Automation Date: Tue, 19 May 2026 06:34:09 +0000 Subject: [PATCH] Releasing version 3.83.0 Co-authored-by: Harsh Kumar --- CHANGELOG.rst | 55 + requirements.txt | 4 +- .../bds/src/oci_cli_bds/generated/bds_cli.py | 28 +- .../tests/integ/test_containerengine.py | 30 +- services/costad/__init__.py | 4 + services/costad/src/__init__.py | 4 + .../costad/src/oci_cli_cost_ad/__init__.py | 4 + .../src/oci_cli_cost_ad/generated/__init__.py | 4 + .../generated/client_mappings.py | 14 + .../oci_cli_cost_ad/generated/costad_cli.py | 999 ++++++++++++++++++ services/costad/tests/__init__.py | 4 + .../tests/util/generated/command_to_api.py | 21 + .../generated/databasetoolsruntime_cli.py | 4 +- .../generated/generativeaiinference_cli.py | 78 +- .../tests/util/generated/command_to_api.py | 1 + .../generated/dbsystem_cli.py | 220 ++++ .../test_object_storage_bulk_operations.py | 2 +- .../test_object_storage_sync_download.py | 4 +- .../test_object_storage_sync_empty_folder.py | 5 +- .../resourceanalyticsinstance_cli.py | 18 +- .../unit/test_unit_test_rover_extended.py | 2 +- .../generated/streamadmin_cli.py | 557 +++++++--- .../tests/util/generated/command_to_api.py | 4 + setup.py | 2 +- src/oci_cli/cli_util.py | 2 +- .../cli_case_insensitive_choice.py | 2 +- src/oci_cli/service_mapping.py | 7 +- src/oci_cli/version.py | 2 +- tests/test_json_skeleton_command_coverage.py | 2 +- 29 files changed, 1906 insertions(+), 177 deletions(-) create mode 100644 services/costad/__init__.py create mode 100644 services/costad/src/__init__.py create mode 100644 services/costad/src/oci_cli_cost_ad/__init__.py create mode 100644 services/costad/src/oci_cli_cost_ad/generated/__init__.py create mode 100644 services/costad/src/oci_cli_cost_ad/generated/client_mappings.py create mode 100644 services/costad/src/oci_cli_cost_ad/generated/costad_cli.py create mode 100644 services/costad/tests/__init__.py create mode 100644 services/costad/tests/util/generated/command_to_api.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 448174ed9..974c6384a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,61 @@ All notable changes to this project will be documented in this file. The format is based on `Keep a Changelog `__. +3.83.0 - 2026-05-19 +------------------- +Added +~~~~~ +* Generative AI Inference service + + * Support for new optional parameter ``--guardrail-version-config`` to support applying guardrails with guardrail version + + * ``oci generative-ai-inference apply-guardrails-result apply-guardrails --guardrail-version-config`` + * ``oci generative-ai-inference apply-guardrails-result apply-guardrails-guardrails-text-input --guardrail-version-config`` + + * Support to list all the OCI GenAI Guardrails version with their accuracy and performance + + * ``oci generative-ai-inference guardrail-version-collection list-guardrail-versions`` + +* Support for new optional parameter ``--compute-count`` for compute count options in Resource Analytics service + + * ``oci resource-analytics resource-analytics-instance create --compute-count`` + +* Support for the Cost Anomaly Detection service + + * ``oci costad`` + +* Support for new optional parameter ``--heterogeneous-shapes`` to provide a heterogeneous shape to replace a cluster node in Big Data Service + + * ``oci bds instance replace-node --heterogeneous-shapes`` + +* Streaming service + + * Support for new optional parameters ``--max-wait-seconds``, ``--wait-for-state`` and ``--wait-interval-seconds`` for commands to change compartments + + * ``oci streaming admin connect-harness change-compartment --max-wait-seconds, --wait-for-state, --wait-interval-seconds`` + * ``oci streaming admin stream change-compartment --max-wait-seconds, --wait-for-state, --wait-interval-seconds`` + * ``oci streaming admin stream-pool change-compartment --max-wait-seconds, --wait-for-state, --wait-interval-seconds`` + + * Support for WorkRequest APIs to track progress of create/update/delete operations of Stream, Stream Pool and Kafka Connect Configuration resources. + + * ``oci streaming admin work-request get`` + * ``oci streaming admin work-request-error-collection list-work-request-errors`` + * ``oci streaming admin work-request-log-entry list-work-request-logs`` + * ``oci streaming admin work-request-summary-collection list-work-requests`` + +Changed +~~~~~~~ +* Big Data service + + * [BREAKING] Removed optional parameters ``--cluster-admin-password`` and ``--secret-id`` to create a BDS certificate configuration + + * ``oci bds instance create-bds-certificate-configuration`` + + * ``--node-backup-id`` is now an optional parameter to repace a node of a BDS cluster from backup + + * ``oci bds instance replace-node`` + + 3.82.0 - 2026-05-12 ------------------- Added diff --git a/requirements.txt b/requirements.txt index cbcd6c7c9..0377c4241 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,7 +15,7 @@ Jinja2>=3.1.5,<4.0.0; python_version >= '3.7' jmespath>=0.10.0,<=1.0.1 ndg-httpsclient==0.4.2 mock==2.0.0 -oci==2.174.0 +oci==2.175.0 packaging>=22.0,<25.0; python_version > '3.8' packaging==20.2; python_version <= '3.8' pluggy==0.13.0 @@ -55,4 +55,4 @@ setuptools==68.0.0; python_version == '3.7' setuptools==59.6.0; python_version == '3.6' # this is required because of python 3.6 requests dependency version bound urllib3==2.6.3; python_version >= '3.10' -urllib3==1.26.20; python_version < '3.10' +urllib3==1.26.20; python_version < '3.10' \ No newline at end of file diff --git a/services/bds/src/oci_cli_bds/generated/bds_cli.py b/services/bds/src/oci_cli_bds/generated/bds_cli.py index 83140af8a..d4d5aa835 100644 --- a/services/bds/src/oci_cli_bds/generated/bds_cli.py +++ b/services/bds/src/oci_cli_bds/generated/bds_cli.py @@ -1801,8 +1801,6 @@ def create_bds_capacity_report(ctx, from_json, compartment_id, shape_availabilit @cli_util.option('--certificate-type', required=True, help=u"""The type of the BDS certificate configuration, also the type of the BDS certificates which will be generated by the BDS certificate configuration.""") @cli_util.option('--certificate-authority-id', help=u"""The OCID of the certificate authority which is associated with this certificate configuration.""") @cli_util.option('--compartment-id', help=u"""The OCID of the compartment of the certificate authority connecting to this certificate configuration.""") -@cli_util.option('--cluster-admin-password', help=u"""Base-64 encoded password for the cluster admin user.""") -@cli_util.option('--secret-id', help=u"""The secretId for the clusterAdminPassword.""") @cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "FAILED", "SUCCEEDED", "CANCELING", "CANCELED"]), multiple=True, help="""This operation asynchronously creates, modifies or deletes a resource and uses a work request to track the progress of the operation. Specify this option to perform the action and then wait until the work request reaches a certain state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACCEPTED --wait-for-state CANCELED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") @cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") @cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the work request has reached the state defined by --wait-for-state. Defaults to 30 seconds.""") @@ -1811,7 +1809,7 @@ def create_bds_capacity_report(ctx, from_json, compartment_id, shape_availabilit @click.pass_context @json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}) @cli_util.wrap_exceptions -def create_bds_certificate_configuration(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, bds_instance_id, display_name, certificate_type, certificate_authority_id, compartment_id, cluster_admin_password, secret_id): +def create_bds_certificate_configuration(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, bds_instance_id, display_name, certificate_type, certificate_authority_id, compartment_id): if isinstance(bds_instance_id, six.string_types) and len(bds_instance_id.strip()) == 0: raise click.UsageError('Parameter --bds-instance-id cannot be whitespace or empty string') @@ -1829,12 +1827,6 @@ def create_bds_certificate_configuration(ctx, from_json, wait_for_state, max_wai if compartment_id is not None: _details['compartmentId'] = compartment_id - if cluster_admin_password is not None: - _details['clusterAdminPassword'] = cluster_admin_password - - if secret_id is not None: - _details['secretId'] = secret_id - client = cli_util.build_client('bds', 'bds', ctx) result = client.create_bds_certificate_configuration( bds_instance_id=bds_instance_id, @@ -4917,7 +4909,7 @@ def list_bds_api_keys(ctx, from_json, all_pages, page_size, bds_instance_id, lif @cli_util.option('--sort-by', type=custom_types.CliCaseInsensitiveChoice(["timeCreated", "displayName"]), help=u"""The field to sort by. Only one sort order may be provided. Default order for timeCreated is descending. Default order for displayName is ascending. If no value is specified timeCreated is default.""") @cli_util.option('--sort-order', type=custom_types.CliCaseInsensitiveChoice(["ASC", "DESC"]), help=u"""The sort order to use, either 'asc' or 'desc'.""") @cli_util.option('--display-name', help=u"""A filter to return only resources that match the entire display name given.""") -@cli_util.option('--lifecycle-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED"]), help=u"""The state of the BdsCertificateConfiguration.""") +@cli_util.option('--lifecycle-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED", "UPDATING"]), help=u"""The state of the BdsCertificateConfiguration.""") @cli_util.option('--all', 'all_pages', is_flag=True, help="""Fetches all pages of results. If you provide this option, then you cannot provide the --limit option.""") @cli_util.option('--page-size', type=click.INT, help="""When fetching results, the number of results to fetch per call. Only valid when used with --all or --limit, and ignored otherwise.""") @json_skeleton_utils.get_cli_json_input_option({}) @@ -6828,20 +6820,21 @@ def renew_certificate(ctx, from_json, wait_for_state, max_wait_seconds, wait_int @bds_instance_group.command(name=cli_util.override('bds.replace_node.command_name', 'replace-node'), help=u"""Replaces a node of a Big Data Service cluster from backup. \n[Command Reference](replaceNode)""") @cli_util.option('--bds-instance-id', required=True, help=u"""The OCID of the cluster.""") @cli_util.option('--node-host-name', required=True, help=u"""Host name of the node to replace. MASTER, UTILITY and EDGE node are only supported types""") -@cli_util.option('--node-backup-id', required=True, help=u"""The id of the nodeBackup to use for replacing the node.""") +@cli_util.option('--node-backup-id', help=u"""The id of the nodeBackup to use for replacing the node.""") @cli_util.option('--cluster-admin-password', help=u"""Base-64 encoded password for the cluster admin user.""") +@cli_util.option('--heterogeneous-shapes', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Heterogeneous shape of the node if the default shape is not available.""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) @cli_util.option('--secret-id', help=u"""The secretId for the clusterAdminPassword.""") @cli_util.option('--shape', help=u"""Shape of the new vm when replacing the node. If not provided, BDS will attempt to replace the node with the shape of current node.""") @cli_util.option('--if-match', help=u"""This if-match is for the BdsInstance. For optimistic concurrency control. In the PUT or DELETE call for a resource, set the `if-match` parameter to the value of the etag from a previous GET or POST response for that resource. The resource will be updated or deleted only if the etag you provide matches the resource's current etag value.""") @cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "FAILED", "SUCCEEDED", "CANCELING", "CANCELED"]), multiple=True, help="""This operation asynchronously creates, modifies or deletes a resource and uses a work request to track the progress of the operation. Specify this option to perform the action and then wait until the work request reaches a certain state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACCEPTED --wait-for-state CANCELED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") @cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") @cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the work request has reached the state defined by --wait-for-state. Defaults to 30 seconds.""") -@json_skeleton_utils.get_cli_json_input_option({}) +@json_skeleton_utils.get_cli_json_input_option({'heterogeneous-shapes': {'module': 'bds', 'class': 'list[string]'}}) @cli_util.help_option @click.pass_context -@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}) +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'heterogeneous-shapes': {'module': 'bds', 'class': 'list[string]'}}) @cli_util.wrap_exceptions -def replace_node(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, bds_instance_id, node_host_name, node_backup_id, cluster_admin_password, secret_id, shape, if_match): +def replace_node(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, bds_instance_id, node_host_name, node_backup_id, cluster_admin_password, heterogeneous_shapes, secret_id, shape, if_match): if isinstance(bds_instance_id, six.string_types) and len(bds_instance_id.strip()) == 0: raise click.UsageError('Parameter --bds-instance-id cannot be whitespace or empty string') @@ -6853,11 +6846,16 @@ def replace_node(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval _details = {} _details['nodeHostName'] = node_host_name - _details['nodeBackupId'] = node_backup_id + + if node_backup_id is not None: + _details['nodeBackupId'] = node_backup_id if cluster_admin_password is not None: _details['clusterAdminPassword'] = cluster_admin_password + if heterogeneous_shapes is not None: + _details['heterogeneousShapes'] = cli_util.parse_json_parameter("heterogeneous_shapes", heterogeneous_shapes) + if secret_id is not None: _details['secretId'] = secret_id diff --git a/services/container_engine/tests/integ/test_containerengine.py b/services/container_engine/tests/integ/test_containerengine.py index f664ac22f..b601f0bcb 100644 --- a/services/container_engine/tests/integ/test_containerengine.py +++ b/services/container_engine/tests/integ/test_containerengine.py @@ -373,12 +373,12 @@ def test_create_kubeconfig_1(config_file, config_profile, oce_cluster, request): util.validate_response(result, json_response_expected=False) # Check that a file got created at default kubeconfig location - assert(os.path.isfile(config_file_path)) + assert (os.path.isfile(config_file_path)) # Check if it is a valid yaml. yaml load will raise an exception in case of invalid yaml with open(config_file_path, 'r') as f: kubeconfig = yaml.safe_load(f) # Check there is only ONE cluster, user and context in the downloaded kubeconfig for this test. - assert(len(kubeconfig['clusters']) == 1) + assert (len(kubeconfig['clusters']) == 1) assert (len(kubeconfig['contexts']) == 1) assert (len(kubeconfig['users']) == 1) @@ -437,9 +437,9 @@ def test_create_kubeconfig_2(config_file, config_profile, oce_cluster, request): with open(config_file_path, 'r') as f: kubeconfig = yaml.safe_load(f) # Check there is ONE more cluster, user and context added in the merged kubeconnfig file. - assert(len(kubeconfig['clusters']) == len(sample_kubeconfig_yaml['clusters']) + 1) - assert(len(kubeconfig['contexts']) == len(sample_kubeconfig_yaml['contexts']) + 1) - assert(len(kubeconfig['users']) == len(sample_kubeconfig_yaml['users']) + 1) + assert (len(kubeconfig['clusters']) == len(sample_kubeconfig_yaml['clusters']) + 1) + assert (len(kubeconfig['contexts']) == len(sample_kubeconfig_yaml['contexts']) + 1) + assert (len(kubeconfig['users']) == len(sample_kubeconfig_yaml['users']) + 1) # TEST 2B # For this test, execute the command again @@ -450,9 +450,9 @@ def test_create_kubeconfig_2(config_file, config_profile, oce_cluster, request): with open(config_file_path, 'r') as f: kubeconfig2 = yaml.safe_load(f) # Check the number of clusters, users and contexts remained the same after the merge - assert(len(kubeconfig['clusters']) == len(kubeconfig2['clusters'])) - assert(len(kubeconfig['contexts']) == len(kubeconfig2['contexts'])) - assert(len(kubeconfig['users']) == len(kubeconfig2['users'])) + assert (len(kubeconfig['clusters']) == len(kubeconfig2['clusters'])) + assert (len(kubeconfig['contexts']) == len(kubeconfig2['contexts'])) + assert (len(kubeconfig['users']) == len(kubeconfig2['users'])) # INPUT: @@ -479,12 +479,12 @@ def test_create_kubeconfig_3(config_file, config_profile, oce_cluster, request): util.validate_response(result, json_response_expected=False) # Check that a file got created at user provided kubeconfig location - assert(os.path.isfile(config_file_path)) + assert (os.path.isfile(config_file_path)) # Check if it is a valid yaml. yaml load will raise an exception in case of invalid yaml with open(config_file_path, 'r') as f: kubeconfig = yaml.safe_load(f) # Check there is only ONE cluster, user and context in the downloaded kubeconfig for this test. - assert(len(kubeconfig['clusters']) == 1) + assert (len(kubeconfig['clusters']) == 1) assert (len(kubeconfig['contexts']) == 1) assert (len(kubeconfig['users']) == 1) @@ -522,7 +522,7 @@ def test_create_kubeconfig_4(config_file, config_profile, oce_cluster, request): with open(config_file_path, 'r') as f: kubeconfig = yaml.safe_load(f) # Check there is only ONE cluster, user and context in the downloaded kubeconfig for this test. - assert(len(kubeconfig['clusters']) == 1) + assert (len(kubeconfig['clusters']) == 1) assert (len(kubeconfig['contexts']) == 1) assert (len(kubeconfig['users']) == 1) @@ -566,11 +566,11 @@ def test_create_kubeconfig_5(config_file, config_profile, oce_cluster, request): with open(config_file_path, 'r') as f: kubeconfig = yaml.safe_load(f) # Check there is only ONE cluster, user and context in the downloaded kubeconfig for this test. - assert(len(kubeconfig['clusters']) == 1) + assert (len(kubeconfig['clusters']) == 1) assert (len(kubeconfig['contexts']) == 1) assert (len(kubeconfig['users']) == 1) # Check that the cluster key has changed indicating we did overwrite old cluster content with new cluster content - assert(kubeconfig['clusters'] != sample_kubeconfig_yaml['clusters']) + assert (kubeconfig['clusters'] != sample_kubeconfig_yaml['clusters']) # INPUT: @@ -597,12 +597,12 @@ def test_create_kubeconfig_6(config_file, config_profile, oce_cluster, request): util.validate_response(result, json_response_expected=False) # Check that a file got created at default kubeconfig location - assert(os.path.isfile(config_file_path)) + assert (os.path.isfile(config_file_path)) # Check if it is a valid yaml. yaml load will raise an exception in case of invalid yaml with open(config_file_path, 'r') as f: kubeconfig = yaml.safe_load(f) # Check there is only ONE cluster, user and context in the downloaded kubeconfig for this test. - assert(len(kubeconfig['clusters']) == 1) + assert (len(kubeconfig['clusters']) == 1) assert (len(kubeconfig['contexts']) == 1) assert (len(kubeconfig['users']) == 1) diff --git a/services/costad/__init__.py b/services/costad/__init__.py new file mode 100644 index 000000000..bbc084f8d --- /dev/null +++ b/services/costad/__init__.py @@ -0,0 +1,4 @@ +# coding: utf-8 +# Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. +# NOTE: This class is auto generated by OracleSDKGenerator. DO NOT EDIT. API Version: 20190111 diff --git a/services/costad/src/__init__.py b/services/costad/src/__init__.py new file mode 100644 index 000000000..bbc084f8d --- /dev/null +++ b/services/costad/src/__init__.py @@ -0,0 +1,4 @@ +# coding: utf-8 +# Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. +# NOTE: This class is auto generated by OracleSDKGenerator. DO NOT EDIT. API Version: 20190111 diff --git a/services/costad/src/oci_cli_cost_ad/__init__.py b/services/costad/src/oci_cli_cost_ad/__init__.py new file mode 100644 index 000000000..bbc084f8d --- /dev/null +++ b/services/costad/src/oci_cli_cost_ad/__init__.py @@ -0,0 +1,4 @@ +# coding: utf-8 +# Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. +# NOTE: This class is auto generated by OracleSDKGenerator. DO NOT EDIT. API Version: 20190111 diff --git a/services/costad/src/oci_cli_cost_ad/generated/__init__.py b/services/costad/src/oci_cli_cost_ad/generated/__init__.py new file mode 100644 index 000000000..bbc084f8d --- /dev/null +++ b/services/costad/src/oci_cli_cost_ad/generated/__init__.py @@ -0,0 +1,4 @@ +# coding: utf-8 +# Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. +# NOTE: This class is auto generated by OracleSDKGenerator. DO NOT EDIT. API Version: 20190111 diff --git a/services/costad/src/oci_cli_cost_ad/generated/client_mappings.py b/services/costad/src/oci_cli_cost_ad/generated/client_mappings.py new file mode 100644 index 000000000..c6cbf7398 --- /dev/null +++ b/services/costad/src/oci_cli_cost_ad/generated/client_mappings.py @@ -0,0 +1,14 @@ +# coding: utf-8 +# Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. +# NOTE: This class is auto generated by OracleSDKGenerator. DO NOT EDIT. API Version: 20190111 + +import oci +from oci_cli.cli_clients import CLIENT_MAP +from oci_cli.cli_clients import MODULE_TO_TYPE_MAPPINGS +from oci.costad import CostAdClient + +MODULE_TO_TYPE_MAPPINGS["costad"] = oci.costad.models.costad_type_mapping +if CLIENT_MAP.get("costad") is None: + CLIENT_MAP["costad"] = {} +CLIENT_MAP["costad"]["cost_ad"] = CostAdClient diff --git a/services/costad/src/oci_cli_cost_ad/generated/costad_cli.py b/services/costad/src/oci_cli_cost_ad/generated/costad_cli.py new file mode 100644 index 000000000..2fb1faa66 --- /dev/null +++ b/services/costad/src/oci_cli_cost_ad/generated/costad_cli.py @@ -0,0 +1,999 @@ +# coding: utf-8 +# Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. +# NOTE: This class is auto generated by OracleSDKGenerator. DO NOT EDIT. API Version: 20190111 + +from __future__ import print_function +import click +import oci # noqa: F401 +import six # noqa: F401 +import sys # noqa: F401 +from oci_cli.cli_root import cli +from oci_cli import cli_constants # noqa: F401 +from oci_cli import cli_util +from oci_cli import json_skeleton_utils +from oci_cli import custom_types # noqa: F401 +from oci_cli.aliasing import CommandGroupWithAlias + + +@cli.command(cli_util.override('costad.costad_root_group.command_name', 'costad'), cls=CommandGroupWithAlias, help=cli_util.override('costad.costad_root_group.help', """Use the CostAd API to manage cost monitor, cost anomaly events and subscription list. For more information, see [Cost Anomaly Detection Overview]."""), short_help=cli_util.override('costad.costad_root_group.short_help', """CostAd API""")) +@cli_util.help_option_group +def costad_root_group(): + pass + + +@click.command(cli_util.override('costad.cost_anomaly_event_group.command_name', 'cost-anomaly-event'), cls=CommandGroupWithAlias, help="""A CostAnomalyEvent.""") +@cli_util.help_option_group +def cost_anomaly_event_group(): + pass + + +@click.command(cli_util.override('costad.cost_alert_subscription_collection_group.command_name', 'cost-alert-subscription-collection'), cls=CommandGroupWithAlias, help="""Results of a costAlertSubscription search. Contains both CostAlertSubscriptionSummary items and other data.""") +@cli_util.help_option_group +def cost_alert_subscription_collection_group(): + pass + + +@click.command(cli_util.override('costad.cost_anomaly_monitor_group.command_name', 'cost-anomaly-monitor'), cls=CommandGroupWithAlias, help="""A CostAnomalyMonitor.""") +@cli_util.help_option_group +def cost_anomaly_monitor_group(): + pass + + +@click.command(cli_util.override('costad.cost_alert_subscription_group.command_name', 'cost-alert-subscription'), cls=CommandGroupWithAlias, help="""A CostAlertSubscription.""") +@cli_util.help_option_group +def cost_alert_subscription_group(): + pass + + +@click.command(cli_util.override('costad.cost_anomaly_monitor_collection_group.command_name', 'cost-anomaly-monitor-collection'), cls=CommandGroupWithAlias, help="""Results of a costAnomalyMonitor search. Contains both CostAnomalyMonitorSummary items and other data.""") +@cli_util.help_option_group +def cost_anomaly_monitor_collection_group(): + pass + + +@click.command(cli_util.override('costad.cost_anomaly_event_collection_group.command_name', 'cost-anomaly-event-collection'), cls=CommandGroupWithAlias, help="""Results of a costAnomalyEvent search. Contains both CostAnomalyEventSummary items and other data.""") +@cli_util.help_option_group +def cost_anomaly_event_collection_group(): + pass + + +costad_root_group.add_command(cost_anomaly_event_group) +costad_root_group.add_command(cost_alert_subscription_collection_group) +costad_root_group.add_command(cost_anomaly_monitor_group) +costad_root_group.add_command(cost_alert_subscription_group) +costad_root_group.add_command(cost_anomaly_monitor_collection_group) +costad_root_group.add_command(cost_anomaly_event_collection_group) + + +@cost_alert_subscription_group.command(name=cli_util.override('costad.create_cost_alert_subscription.command_name', 'create'), help=u"""Creates a new CostAlert Subscription. \n[Command Reference](createCostAlertSubscription)""") +@cli_util.option('--compartment-id', required=True, help=u"""The OCID of the compartment.""") +@cli_util.option('--name', required=True, help=u"""The name of the cost alert subscription. Avoid entering confidential information.""") +@cli_util.option('--channels', required=True, help=u"""The notification channels string.""") +@cli_util.option('--description', help=u"""The description of the cost alert subscription.""") +@cli_util.option('--defined-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Defined tags for this resource. Each key is predefined and scoped to a namespace. For more information, see [Resource Tags]. + +Example: `{\"Operations\": {\"CostCenter\": \"42\"}}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--freeform-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Free-form tags for this resource. Each tag is a simple key-value pair with no predefined name, type, or namespace. For more information, see [Resource Tags]. + +Example: `{\"Department\": \"Finance\"}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACTIVE", "INACTIVE"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACTIVE --wait-for-state INACTIVE would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@json_skeleton_utils.get_cli_json_input_option({'defined-tags': {'module': 'costad', 'class': 'dict(str, dict(str, object))'}, 'freeform-tags': {'module': 'costad', 'class': 'dict(str, string)'}}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'defined-tags': {'module': 'costad', 'class': 'dict(str, dict(str, object))'}, 'freeform-tags': {'module': 'costad', 'class': 'dict(str, string)'}}, output_type={'module': 'costad', 'class': 'CostAlertSubscription'}) +@cli_util.wrap_exceptions +def create_cost_alert_subscription(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, compartment_id, name, channels, description, defined_tags, freeform_tags): + + kwargs = {} + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + + _details = {} + _details['compartmentId'] = compartment_id + _details['name'] = name + _details['channels'] = channels + + if description is not None: + _details['description'] = description + + if defined_tags is not None: + _details['definedTags'] = cli_util.parse_json_parameter("defined_tags", defined_tags) + + if freeform_tags is not None: + _details['freeformTags'] = cli_util.parse_json_parameter("freeform_tags", freeform_tags) + + client = cli_util.build_client('costad', 'cost_ad', ctx) + result = client.create_cost_alert_subscription( + create_cost_alert_subscription_details=_details, + **kwargs + ) + if wait_for_state: + + if hasattr(client, 'get_cost_alert_subscription') and callable(getattr(client, 'get_cost_alert_subscription')): + try: + wait_period_kwargs = {} + if max_wait_seconds is not None: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds is not None: + wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + + click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_cost_alert_subscription(result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + except oci.exceptions.MaximumWaitTimeExceeded as e: + # If we fail, we should show an error, but we should still provide the information to the customer + click.echo('Failed to wait until the resource entered the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + sys.exit(2) + except Exception: + click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + raise + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@cost_anomaly_monitor_group.command(name=cli_util.override('costad.create_cost_anomaly_monitor.command_name', 'create'), help=u"""Creates a new costAnomaly Monitor. \n[Command Reference](createCostAnomalyMonitor)""") +@cli_util.option('--compartment-id', required=True, help=u"""The OCID of the compartment.""") +@cli_util.option('--name', required=True, help=u"""The name of the cost anomaly monitor. Avoid entering confidential information.""") +@cli_util.option('--target-resource-filter', required=True, type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--description', help=u"""The description of the cost anomaly monitor.""") +@cli_util.option('--cost-alert-subscription-map', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--defined-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Defined tags for this resource. Each key is predefined and scoped to a namespace. For more information, see [Resource Tags]. + +Example: `{\"Operations\": {\"CostCenter\": \"42\"}}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--freeform-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Free-form tags for this resource. Each tag is a simple key-value pair with no predefined name, type, or namespace. For more information, see [Resource Tags]. + +Example: `{\"Department\": \"Finance\"}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACTIVE", "INACTIVE", "DELETED"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACTIVE --wait-for-state DELETED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@json_skeleton_utils.get_cli_json_input_option({'target-resource-filter': {'module': 'costad', 'class': 'TargetResourceFilter'}, 'cost-alert-subscription-map': {'module': 'costad', 'class': 'CostAlertSubscriptionMap'}, 'defined-tags': {'module': 'costad', 'class': 'dict(str, dict(str, object))'}, 'freeform-tags': {'module': 'costad', 'class': 'dict(str, string)'}}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'target-resource-filter': {'module': 'costad', 'class': 'TargetResourceFilter'}, 'cost-alert-subscription-map': {'module': 'costad', 'class': 'CostAlertSubscriptionMap'}, 'defined-tags': {'module': 'costad', 'class': 'dict(str, dict(str, object))'}, 'freeform-tags': {'module': 'costad', 'class': 'dict(str, string)'}}, output_type={'module': 'costad', 'class': 'CostAnomalyMonitor'}) +@cli_util.wrap_exceptions +def create_cost_anomaly_monitor(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, compartment_id, name, target_resource_filter, description, cost_alert_subscription_map, defined_tags, freeform_tags): + + kwargs = {} + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + + _details = {} + _details['compartmentId'] = compartment_id + _details['name'] = name + _details['targetResourceFilter'] = cli_util.parse_json_parameter("target_resource_filter", target_resource_filter) + + if description is not None: + _details['description'] = description + + if cost_alert_subscription_map is not None: + _details['costAlertSubscriptionMap'] = cli_util.parse_json_parameter("cost_alert_subscription_map", cost_alert_subscription_map) + + if defined_tags is not None: + _details['definedTags'] = cli_util.parse_json_parameter("defined_tags", defined_tags) + + if freeform_tags is not None: + _details['freeformTags'] = cli_util.parse_json_parameter("freeform_tags", freeform_tags) + + client = cli_util.build_client('costad', 'cost_ad', ctx) + result = client.create_cost_anomaly_monitor( + create_cost_anomaly_monitor_details=_details, + **kwargs + ) + if wait_for_state: + + if hasattr(client, 'get_cost_anomaly_monitor') and callable(getattr(client, 'get_cost_anomaly_monitor')): + try: + wait_period_kwargs = {} + if max_wait_seconds is not None: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds is not None: + wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + + click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_cost_anomaly_monitor(result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + except oci.exceptions.MaximumWaitTimeExceeded as e: + # If we fail, we should show an error, but we should still provide the information to the customer + click.echo('Failed to wait until the resource entered the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + sys.exit(2) + except Exception: + click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + raise + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@cost_alert_subscription_group.command(name=cli_util.override('costad.delete_cost_alert_subscription.command_name', 'delete'), help=u"""Deletes a specified CostAlertSubscription resource. \n[Command Reference](deleteCostAlertSubscription)""") +@cli_util.option('--subscription-id', required=True, help=u"""The unique costAlertSubscription OCID.""") +@cli_util.option('--if-match', help=u"""For optimistic concurrency control. In the PUT or DELETE call for a resource, set the `if-match` parameter to the value of the etag from a previous GET or POST response for that resource. The resource will be updated or deleted only if the etag you provide matches the resource's current etag value.""") +@cli_util.confirm_delete_option +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACTIVE", "INACTIVE"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACTIVE --wait-for-state INACTIVE would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@json_skeleton_utils.get_cli_json_input_option({}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}) +@cli_util.wrap_exceptions +def delete_cost_alert_subscription(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, subscription_id, if_match): + + if isinstance(subscription_id, six.string_types) and len(subscription_id.strip()) == 0: + raise click.UsageError('Parameter --subscription-id cannot be whitespace or empty string') + + kwargs = {} + if if_match is not None: + kwargs['if_match'] = if_match + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('costad', 'cost_ad', ctx) + result = client.delete_cost_alert_subscription( + cost_alert_subscription_id=subscription_id, + **kwargs + ) + if wait_for_state: + + if hasattr(client, 'get_cost_alert_subscription') and callable(getattr(client, 'get_cost_alert_subscription')): + try: + wait_period_kwargs = {} + if max_wait_seconds is not None: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds is not None: + wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + + click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) + oci.wait_until(client, client.get_cost_alert_subscription(subscription_id), 'lifecycle_state', wait_for_state, succeed_on_not_found=True, **wait_period_kwargs) + except oci.exceptions.ServiceError as e: + # We make an initial service call so we can pass the result to oci.wait_until(), however if we are waiting on the + # outcome of a delete operation it is possible that the resource is already gone and so the initial service call + # will result in an exception that reflects a HTTP 404. In this case, we can exit with success (rather than raising + # the exception) since this would have been the behaviour in the waiter anyway (as for delete we provide the argument + # succeed_on_not_found=True to the waiter). + # + # Any non-404 should still result in the exception being thrown. + if e.status == 404: + pass + else: + raise + except oci.exceptions.MaximumWaitTimeExceeded as e: + # If we fail, we should show an error, but we should still provide the information to the customer + click.echo('Failed to wait until the resource entered the specified state. Please retrieve the resource to find its current state', file=sys.stderr) + cli_util.render_response(result, ctx) + sys.exit(2) + except Exception: + click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + raise + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@cost_anomaly_monitor_group.command(name=cli_util.override('costad.delete_cost_anomaly_monitor.command_name', 'delete'), help=u"""Deletes a specified CostAnomalyMonitor resource. \n[Command Reference](deleteCostAnomalyMonitor)""") +@cli_util.option('--cost-anomaly-monitor-id', required=True, help=u"""The unique costAnomalyMonitor OCID.""") +@cli_util.option('--if-match', help=u"""For optimistic concurrency control. In the PUT or DELETE call for a resource, set the `if-match` parameter to the value of the etag from a previous GET or POST response for that resource. The resource will be updated or deleted only if the etag you provide matches the resource's current etag value.""") +@cli_util.confirm_delete_option +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACTIVE", "INACTIVE", "DELETED"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACTIVE --wait-for-state DELETED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@json_skeleton_utils.get_cli_json_input_option({}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}) +@cli_util.wrap_exceptions +def delete_cost_anomaly_monitor(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, cost_anomaly_monitor_id, if_match): + + if isinstance(cost_anomaly_monitor_id, six.string_types) and len(cost_anomaly_monitor_id.strip()) == 0: + raise click.UsageError('Parameter --cost-anomaly-monitor-id cannot be whitespace or empty string') + + kwargs = {} + if if_match is not None: + kwargs['if_match'] = if_match + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('costad', 'cost_ad', ctx) + result = client.delete_cost_anomaly_monitor( + cost_anomaly_monitor_id=cost_anomaly_monitor_id, + **kwargs + ) + if wait_for_state: + + if hasattr(client, 'get_cost_anomaly_monitor') and callable(getattr(client, 'get_cost_anomaly_monitor')): + try: + wait_period_kwargs = {} + if max_wait_seconds is not None: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds is not None: + wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + + click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) + oci.wait_until(client, client.get_cost_anomaly_monitor(cost_anomaly_monitor_id), 'lifecycle_state', wait_for_state, succeed_on_not_found=True, **wait_period_kwargs) + except oci.exceptions.ServiceError as e: + # We make an initial service call so we can pass the result to oci.wait_until(), however if we are waiting on the + # outcome of a delete operation it is possible that the resource is already gone and so the initial service call + # will result in an exception that reflects a HTTP 404. In this case, we can exit with success (rather than raising + # the exception) since this would have been the behaviour in the waiter anyway (as for delete we provide the argument + # succeed_on_not_found=True to the waiter). + # + # Any non-404 should still result in the exception being thrown. + if e.status == 404: + pass + else: + raise + except oci.exceptions.MaximumWaitTimeExceeded as e: + # If we fail, we should show an error, but we should still provide the information to the customer + click.echo('Failed to wait until the resource entered the specified state. Please retrieve the resource to find its current state', file=sys.stderr) + cli_util.render_response(result, ctx) + sys.exit(2) + except Exception: + click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + raise + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@cost_anomaly_monitor_group.command(name=cli_util.override('costad.disable_cost_anomaly_monitor.command_name', 'disable'), help=u"""Disables the cost anomaly monitor. This stops cost anomaly detection for targeted resource(s). \n[Command Reference](disableCostAnomalyMonitor)""") +@cli_util.option('--cost-anomaly-monitor-id', required=True, help=u"""The unique costAnomalyMonitor OCID.""") +@cli_util.option('--if-match', help=u"""For optimistic concurrency control. In the PUT or DELETE call for a resource, set the `if-match` parameter to the value of the etag from a previous GET or POST response for that resource. The resource will be updated or deleted only if the etag you provide matches the resource's current etag value.""") +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACTIVE", "INACTIVE", "DELETED"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACTIVE --wait-for-state DELETED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@json_skeleton_utils.get_cli_json_input_option({}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}, output_type={'module': 'costad', 'class': 'CostAnomalyMonitor'}) +@cli_util.wrap_exceptions +def disable_cost_anomaly_monitor(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, cost_anomaly_monitor_id, if_match): + + if isinstance(cost_anomaly_monitor_id, six.string_types) and len(cost_anomaly_monitor_id.strip()) == 0: + raise click.UsageError('Parameter --cost-anomaly-monitor-id cannot be whitespace or empty string') + + kwargs = {} + if if_match is not None: + kwargs['if_match'] = if_match + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('costad', 'cost_ad', ctx) + result = client.disable_cost_anomaly_monitor( + cost_anomaly_monitor_id=cost_anomaly_monitor_id, + **kwargs + ) + if wait_for_state: + + if hasattr(client, 'get_cost_anomaly_monitor') and callable(getattr(client, 'get_cost_anomaly_monitor')): + try: + wait_period_kwargs = {} + if max_wait_seconds is not None: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds is not None: + wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + + click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_cost_anomaly_monitor(result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + except oci.exceptions.MaximumWaitTimeExceeded as e: + # If we fail, we should show an error, but we should still provide the information to the customer + click.echo('Failed to wait until the resource entered the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + sys.exit(2) + except Exception: + click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + raise + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@cost_anomaly_monitor_group.command(name=cli_util.override('costad.enable_cost_anomaly_monitor.command_name', 'enable'), help=u"""Enables the cost anomaly monitor. This (re)starts the cost anomaly detection for targeted resource(s). \n[Command Reference](enableCostAnomalyMonitor)""") +@cli_util.option('--cost-anomaly-monitor-id', required=True, help=u"""The unique costAnomalyMonitor OCID.""") +@cli_util.option('--if-match', help=u"""For optimistic concurrency control. In the PUT or DELETE call for a resource, set the `if-match` parameter to the value of the etag from a previous GET or POST response for that resource. The resource will be updated or deleted only if the etag you provide matches the resource's current etag value.""") +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACTIVE", "INACTIVE", "DELETED"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACTIVE --wait-for-state DELETED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@json_skeleton_utils.get_cli_json_input_option({}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}, output_type={'module': 'costad', 'class': 'CostAnomalyMonitor'}) +@cli_util.wrap_exceptions +def enable_cost_anomaly_monitor(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, cost_anomaly_monitor_id, if_match): + + if isinstance(cost_anomaly_monitor_id, six.string_types) and len(cost_anomaly_monitor_id.strip()) == 0: + raise click.UsageError('Parameter --cost-anomaly-monitor-id cannot be whitespace or empty string') + + kwargs = {} + if if_match is not None: + kwargs['if_match'] = if_match + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('costad', 'cost_ad', ctx) + result = client.enable_cost_anomaly_monitor( + cost_anomaly_monitor_id=cost_anomaly_monitor_id, + **kwargs + ) + if wait_for_state: + + if hasattr(client, 'get_cost_anomaly_monitor') and callable(getattr(client, 'get_cost_anomaly_monitor')): + try: + wait_period_kwargs = {} + if max_wait_seconds is not None: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds is not None: + wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + + click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_cost_anomaly_monitor(result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + except oci.exceptions.MaximumWaitTimeExceeded as e: + # If we fail, we should show an error, but we should still provide the information to the customer + click.echo('Failed to wait until the resource entered the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + sys.exit(2) + except Exception: + click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + raise + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@cost_alert_subscription_group.command(name=cli_util.override('costad.get_cost_alert_subscription.command_name', 'get'), help=u"""Gets a CostAlertSubscription by the identifier. \n[Command Reference](getCostAlertSubscription)""") +@cli_util.option('--subscription-id', required=True, help=u"""The unique costAlertSubscription OCID.""") +@json_skeleton_utils.get_cli_json_input_option({}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}, output_type={'module': 'costad', 'class': 'CostAlertSubscription'}) +@cli_util.wrap_exceptions +def get_cost_alert_subscription(ctx, from_json, subscription_id): + + if isinstance(subscription_id, six.string_types) and len(subscription_id.strip()) == 0: + raise click.UsageError('Parameter --subscription-id cannot be whitespace or empty string') + + kwargs = {} + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('costad', 'cost_ad', ctx) + result = client.get_cost_alert_subscription( + cost_alert_subscription_id=subscription_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@cost_anomaly_event_group.command(name=cli_util.override('costad.get_cost_anomaly_event.command_name', 'get'), help=u"""Gets a CostAnomalyEvent by the identifier. \n[Command Reference](getCostAnomalyEvent)""") +@cli_util.option('--cost-anomaly-event-id', required=True, help=u"""The unique costAnomalyEventId OCID.""") +@json_skeleton_utils.get_cli_json_input_option({}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}, output_type={'module': 'costad', 'class': 'CostAnomalyEvent'}) +@cli_util.wrap_exceptions +def get_cost_anomaly_event(ctx, from_json, cost_anomaly_event_id): + + if isinstance(cost_anomaly_event_id, six.string_types) and len(cost_anomaly_event_id.strip()) == 0: + raise click.UsageError('Parameter --cost-anomaly-event-id cannot be whitespace or empty string') + + kwargs = {} + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('costad', 'cost_ad', ctx) + result = client.get_cost_anomaly_event( + cost_anomaly_event_id=cost_anomaly_event_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@cost_anomaly_monitor_group.command(name=cli_util.override('costad.get_cost_anomaly_monitor.command_name', 'get'), help=u"""Gets a CostAnomalyMonitor by the identifier. \n[Command Reference](getCostAnomalyMonitor)""") +@cli_util.option('--cost-anomaly-monitor-id', required=True, help=u"""The unique costAnomalyMonitor OCID.""") +@json_skeleton_utils.get_cli_json_input_option({}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}, output_type={'module': 'costad', 'class': 'CostAnomalyMonitor'}) +@cli_util.wrap_exceptions +def get_cost_anomaly_monitor(ctx, from_json, cost_anomaly_monitor_id): + + if isinstance(cost_anomaly_monitor_id, six.string_types) and len(cost_anomaly_monitor_id.strip()) == 0: + raise click.UsageError('Parameter --cost-anomaly-monitor-id cannot be whitespace or empty string') + + kwargs = {} + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('costad', 'cost_ad', ctx) + result = client.get_cost_anomaly_monitor( + cost_anomaly_monitor_id=cost_anomaly_monitor_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@cost_alert_subscription_collection_group.command(name=cli_util.override('costad.list_cost_alert_subscriptions.command_name', 'list-subs'), help=u"""Gets a list of Cost Alert Subscription in a compartment. \n[Command Reference](listCostAlertSubscriptions)""") +@cli_util.option('--compartment-id', required=True, help=u"""The ID of the compartment in which to list resources.""") +@cli_util.option('--limit', type=click.INT, help=u"""The maximum number of items to return.""") +@cli_util.option('--page', help=u"""The page token representing the page at which to start retrieving results. This is usually retrieved from a previous list call.""") +@cli_util.option('--sort-order', type=custom_types.CliCaseInsensitiveChoice(["ASC", "DESC"]), help=u"""The sort order to use, either 'asc' or 'desc'.""") +@cli_util.option('--sort-by', type=custom_types.CliCaseInsensitiveChoice(["timeCreated", "name", "id"]), help=u"""The field to sort by. If not specified, the default is timeCreated. The default sort order for timeCreated is DESC. The default sort order for displayName is ASC in alphanumeric order.""") +@cli_util.option('--name', help=u"""Unique, non-changeable resource name.""") +@cli_util.option('--lifecycle-state', type=custom_types.CliCaseInsensitiveChoice(["ACTIVE", "INACTIVE"]), help=u"""The current state of the cost alert subscription.""") +@cli_util.option('--all', 'all_pages', is_flag=True, help="""Fetches all pages of results. If you provide this option, then you cannot provide the --limit option.""") +@cli_util.option('--page-size', type=click.INT, help="""When fetching results, the number of results to fetch per call. Only valid when used with --all or --limit, and ignored otherwise.""") +@json_skeleton_utils.get_cli_json_input_option({}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}, output_type={'module': 'costad', 'class': 'CostAlertSubscriptionCollection'}) +@cli_util.wrap_exceptions +def list_cost_alert_subscriptions(ctx, from_json, all_pages, page_size, compartment_id, limit, page, sort_order, sort_by, name, lifecycle_state): + + if all_pages and limit: + raise click.UsageError('If you provide the --all option you cannot provide the --limit option') + + kwargs = {} + if limit is not None: + kwargs['limit'] = limit + if page is not None: + kwargs['page'] = page + if sort_order is not None: + kwargs['sort_order'] = sort_order + if sort_by is not None: + kwargs['sort_by'] = sort_by + if name is not None: + kwargs['name'] = name + if lifecycle_state is not None: + kwargs['lifecycle_state'] = lifecycle_state + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('costad', 'cost_ad', ctx) + if all_pages: + if page_size: + kwargs['limit'] = page_size + + result = cli_util.list_call_get_all_results( + client.list_cost_alert_subscriptions, + compartment_id=compartment_id, + **kwargs + ) + elif limit is not None: + result = cli_util.list_call_get_up_to_limit( + client.list_cost_alert_subscriptions, + limit, + page_size, + compartment_id=compartment_id, + **kwargs + ) + else: + result = client.list_cost_alert_subscriptions( + compartment_id=compartment_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@cost_anomaly_event_collection_group.command(name=cli_util.override('costad.list_cost_anomaly_events.command_name', 'list-events'), help=u"""Gets a list of Cost Anomaly Event in a compartment. \n[Command Reference](listCostAnomalyEvents)""") +@cli_util.option('--compartment-id', required=True, help=u"""The ID of the compartment in which to list resources.""") +@cli_util.option('--limit', type=click.INT, help=u"""The maximum number of items to return.""") +@cli_util.option('--page', help=u"""The page token representing the page at which to start retrieving results. This is usually retrieved from a previous list call.""") +@cli_util.option('--sort-order', type=custom_types.CliCaseInsensitiveChoice(["ASC", "DESC"]), help=u"""The sort order to use, either 'asc' or 'desc'.""") +@cli_util.option('--sort-by', type=custom_types.CliCaseInsensitiveChoice(["timeAnomalyEventDate", "costAnomalyName", "id"]), help=u"""The field to sort by. If not specified, the default is timeAnomalyEventDate. The default sort order for timeAnomalyEventDate is DESC. The default sort order for costAnomalyName is ASC in alphanumeric order.""") +@cli_util.option('--name', help=u"""Unique, non-changeable resource name.""") +@cli_util.option('--cost-anomaly-monitor-id', help=u"""The cost monitor ocid.""") +@cli_util.option('--target-tenant-id', multiple=True, help=u"""The target tenantId ocid filter param.""") +@cli_util.option('--start-date', type=custom_types.CLI_DATETIME, help=u"""startDate for anomaly event date.""" + custom_types.CLI_DATETIME.VALID_DATETIME_CLI_HELP_MESSAGE) +@cli_util.option('--end-date', type=custom_types.CLI_DATETIME, help=u"""endDate for anomaly event date.""" + custom_types.CLI_DATETIME.VALID_DATETIME_CLI_HELP_MESSAGE) +@cli_util.option('--ad-event-region', multiple=True, help=u"""region of the anomaly event.""") +@cli_util.option('--cost-impact', help=u"""cost impact (absolute) of the anomaly event.""") +@cli_util.option('--cost-impact-percentage', help=u"""cost impact (percentage) of the anomaly event.""") +@cli_util.option('--all', 'all_pages', is_flag=True, help="""Fetches all pages of results. If you provide this option, then you cannot provide the --limit option.""") +@cli_util.option('--page-size', type=click.INT, help="""When fetching results, the number of results to fetch per call. Only valid when used with --all or --limit, and ignored otherwise.""") +@json_skeleton_utils.get_cli_json_input_option({'target-tenant-id': {'module': 'costad', 'class': 'list[string]'}, 'ad-event-region': {'module': 'costad', 'class': 'list[string]'}}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'target-tenant-id': {'module': 'costad', 'class': 'list[string]'}, 'ad-event-region': {'module': 'costad', 'class': 'list[string]'}}, output_type={'module': 'costad', 'class': 'CostAnomalyEventCollection'}) +@cli_util.wrap_exceptions +def list_cost_anomaly_events(ctx, from_json, all_pages, page_size, compartment_id, limit, page, sort_order, sort_by, name, cost_anomaly_monitor_id, target_tenant_id, start_date, end_date, ad_event_region, cost_impact, cost_impact_percentage): + + if all_pages and limit: + raise click.UsageError('If you provide the --all option you cannot provide the --limit option') + + kwargs = {} + if limit is not None: + kwargs['limit'] = limit + if page is not None: + kwargs['page'] = page + if sort_order is not None: + kwargs['sort_order'] = sort_order + if sort_by is not None: + kwargs['sort_by'] = sort_by + if name is not None: + kwargs['name'] = name + if cost_anomaly_monitor_id is not None: + kwargs['cost_anomaly_monitor_id'] = cost_anomaly_monitor_id + if target_tenant_id is not None and len(target_tenant_id) > 0: + kwargs['target_tenant_id'] = target_tenant_id + if start_date is not None: + kwargs['time_anomaly_event_start_date'] = start_date + if end_date is not None: + kwargs['time_anomaly_event_end_date'] = end_date + if ad_event_region is not None and len(ad_event_region) > 0: + kwargs['region'] = ad_event_region + if cost_impact is not None: + kwargs['cost_impact'] = cost_impact + if cost_impact_percentage is not None: + kwargs['cost_impact_percentage'] = cost_impact_percentage + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('costad', 'cost_ad', ctx) + if all_pages: + if page_size: + kwargs['limit'] = page_size + + result = cli_util.list_call_get_all_results( + client.list_cost_anomaly_events, + compartment_id=compartment_id, + **kwargs + ) + elif limit is not None: + result = cli_util.list_call_get_up_to_limit( + client.list_cost_anomaly_events, + limit, + page_size, + compartment_id=compartment_id, + **kwargs + ) + else: + result = client.list_cost_anomaly_events( + compartment_id=compartment_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@cost_anomaly_monitor_collection_group.command(name=cli_util.override('costad.list_cost_anomaly_monitors.command_name', 'list-monitors'), help=u"""Gets a list of Cost Anomaly Monitors in a compartment. \n[Command Reference](listCostAnomalyMonitors)""") +@cli_util.option('--compartment-id', required=True, help=u"""The ID of the compartment in which to list resources.""") +@cli_util.option('--limit', type=click.INT, help=u"""The maximum number of items to return.""") +@cli_util.option('--page', help=u"""The page token representing the page at which to start retrieving results. This is usually retrieved from a previous list call.""") +@cli_util.option('--sort-order', type=custom_types.CliCaseInsensitiveChoice(["ASC", "DESC"]), help=u"""The sort order to use, either 'asc' or 'desc'.""") +@cli_util.option('--sort-by', type=custom_types.CliCaseInsensitiveChoice(["timeCreated", "name", "id"]), help=u"""The field to sort by. If not specified, the default is timeCreated. The default sort order for timeCreated is DESC. The default sort order for displayName is ASC in alphanumeric order.""") +@cli_util.option('--lifecycle-state', type=custom_types.CliCaseInsensitiveChoice(["ACTIVE", "INACTIVE", "DELETED"]), help=u"""The current state of the cost monitor.""") +@cli_util.option('--name', help=u"""Unique, non-changeable resource name.""") +@cli_util.option('--target-tenant-id', multiple=True, help=u"""The target tenantId ocid filter param.""") +@cli_util.option('--target-region', multiple=True, help=u"""Cost Anomaly Monitor target resource filter region.""") +@cli_util.option('--all', 'all_pages', is_flag=True, help="""Fetches all pages of results. If you provide this option, then you cannot provide the --limit option.""") +@cli_util.option('--page-size', type=click.INT, help="""When fetching results, the number of results to fetch per call. Only valid when used with --all or --limit, and ignored otherwise.""") +@json_skeleton_utils.get_cli_json_input_option({'target-tenant-id': {'module': 'costad', 'class': 'list[string]'}, 'target-region': {'module': 'costad', 'class': 'list[string]'}}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'target-tenant-id': {'module': 'costad', 'class': 'list[string]'}, 'target-region': {'module': 'costad', 'class': 'list[string]'}}, output_type={'module': 'costad', 'class': 'CostAnomalyMonitorCollection'}) +@cli_util.wrap_exceptions +def list_cost_anomaly_monitors(ctx, from_json, all_pages, page_size, compartment_id, limit, page, sort_order, sort_by, lifecycle_state, name, target_tenant_id, target_region): + + if all_pages and limit: + raise click.UsageError('If you provide the --all option you cannot provide the --limit option') + + kwargs = {} + if limit is not None: + kwargs['limit'] = limit + if page is not None: + kwargs['page'] = page + if sort_order is not None: + kwargs['sort_order'] = sort_order + if sort_by is not None: + kwargs['sort_by'] = sort_by + if lifecycle_state is not None: + kwargs['lifecycle_state'] = lifecycle_state + if name is not None: + kwargs['name'] = name + if target_tenant_id is not None and len(target_tenant_id) > 0: + kwargs['target_tenant_id'] = target_tenant_id + if target_region is not None and len(target_region) > 0: + kwargs['region'] = target_region + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('costad', 'cost_ad', ctx) + if all_pages: + if page_size: + kwargs['limit'] = page_size + + result = cli_util.list_call_get_all_results( + client.list_cost_anomaly_monitors, + compartment_id=compartment_id, + **kwargs + ) + elif limit is not None: + result = cli_util.list_call_get_up_to_limit( + client.list_cost_anomaly_monitors, + limit, + page_size, + compartment_id=compartment_id, + **kwargs + ) + else: + result = client.list_cost_anomaly_monitors( + compartment_id=compartment_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@cost_anomaly_event_group.command(name=cli_util.override('costad.summarize_cost_anomaly_event_analytics.command_name', 'anomaly-events-stats'), help=u"""Gets a list of Cost Anomaly Events analytics summary - aggregated metrics for a given time period. \n[Command Reference](summarizeCostAnomalyEventAnalytics)""") +@cli_util.option('--compartment-id', required=True, help=u"""The ID of the compartment in which to list resources.""") +@cli_util.option('--limit', type=click.INT, help=u"""The maximum number of items to return.""") +@cli_util.option('--page', help=u"""The page token representing the page at which to start retrieving results. This is usually retrieved from a previous list call.""") +@cli_util.option('--sort-order', type=custom_types.CliCaseInsensitiveChoice(["ASC", "DESC"]), help=u"""The sort order to use, either 'asc' or 'desc'.""") +@cli_util.option('--sort-by', type=custom_types.CliCaseInsensitiveChoice(["timeAnomalyEventDate", "costAnomalyName", "id"]), help=u"""The field to sort by. If not specified, the default is timeAnomalyEventDate. The default sort order for timeAnomalyEventDate is DESC. The default sort order for costAnomalyName is ASC in alphanumeric order.""") +@cli_util.option('--name', help=u"""Unique, non-changeable resource name.""") +@cli_util.option('--cost-anomaly-monitor-id', help=u"""The cost monitor ocid.""") +@cli_util.option('--target-tenant-id', multiple=True, help=u"""The target tenantId ocid filter param.""") +@cli_util.option('--start-date', type=custom_types.CLI_DATETIME, help=u"""startDate for anomaly event date.""" + custom_types.CLI_DATETIME.VALID_DATETIME_CLI_HELP_MESSAGE) +@cli_util.option('--end-date', type=custom_types.CLI_DATETIME, help=u"""endDate for anomaly event date.""" + custom_types.CLI_DATETIME.VALID_DATETIME_CLI_HELP_MESSAGE) +@cli_util.option('--ad-event-region', multiple=True, help=u"""region of the anomaly event.""") +@cli_util.option('--cost-impact', help=u"""cost impact (absolute) of the anomaly event.""") +@cli_util.option('--cost-impact-percentage', help=u"""cost impact (percentage) of the anomaly event.""") +@json_skeleton_utils.get_cli_json_input_option({'target-tenant-id': {'module': 'costad', 'class': 'list[string]'}, 'ad-event-region': {'module': 'costad', 'class': 'list[string]'}}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'target-tenant-id': {'module': 'costad', 'class': 'list[string]'}, 'ad-event-region': {'module': 'costad', 'class': 'list[string]'}}, output_type={'module': 'costad', 'class': 'CostAnomalyEventAnalyticCollection'}) +@cli_util.wrap_exceptions +def summarize_cost_anomaly_event_analytics(ctx, from_json, compartment_id, limit, page, sort_order, sort_by, name, cost_anomaly_monitor_id, target_tenant_id, start_date, end_date, ad_event_region, cost_impact, cost_impact_percentage): + + kwargs = {} + if limit is not None: + kwargs['limit'] = limit + if page is not None: + kwargs['page'] = page + if sort_order is not None: + kwargs['sort_order'] = sort_order + if sort_by is not None: + kwargs['sort_by'] = sort_by + if name is not None: + kwargs['name'] = name + if cost_anomaly_monitor_id is not None: + kwargs['cost_anomaly_monitor_id'] = cost_anomaly_monitor_id + if target_tenant_id is not None and len(target_tenant_id) > 0: + kwargs['target_tenant_id'] = target_tenant_id + if start_date is not None: + kwargs['time_anomaly_event_start_date'] = start_date + if end_date is not None: + kwargs['time_anomaly_event_end_date'] = end_date + if ad_event_region is not None and len(ad_event_region) > 0: + kwargs['region'] = ad_event_region + if cost_impact is not None: + kwargs['cost_impact'] = cost_impact + if cost_impact_percentage is not None: + kwargs['cost_impact_percentage'] = cost_impact_percentage + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('costad', 'cost_ad', ctx) + result = client.summarize_cost_anomaly_event_analytics( + compartment_id=compartment_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@cost_alert_subscription_group.command(name=cli_util.override('costad.update_cost_alert_subscription.command_name', 'update'), help=u"""Update a CostAlertSubscription identified by the OCID. \n[Command Reference](updateCostAlertSubscription)""") +@cli_util.option('--subscription-id', required=True, help=u"""The unique costAlertSubscription OCID.""") +@cli_util.option('--description', help=u"""The description of the cost alert subscription.""") +@cli_util.option('--channels', help=u"""The notification channels string.""") +@cli_util.option('--defined-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Defined tags for this resource. Each key is predefined and scoped to a namespace. For more information, see [Resource Tags]. + +Example: `{\"Operations\": {\"CostCenter\": \"42\"}}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--freeform-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Free-form tags for this resource. Each tag is a simple key-value pair with no predefined name, type, or namespace. For more information, see [Resource Tags]. + +Example: `{\"Department\": \"Finance\"}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--if-match', help=u"""For optimistic concurrency control. In the PUT or DELETE call for a resource, set the `if-match` parameter to the value of the etag from a previous GET or POST response for that resource. The resource will be updated or deleted only if the etag you provide matches the resource's current etag value.""") +@cli_util.option('--force', help="""Perform update without prompting for confirmation.""", is_flag=True) +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACTIVE", "INACTIVE"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACTIVE --wait-for-state INACTIVE would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@json_skeleton_utils.get_cli_json_input_option({'defined-tags': {'module': 'costad', 'class': 'dict(str, dict(str, object))'}, 'freeform-tags': {'module': 'costad', 'class': 'dict(str, string)'}}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'defined-tags': {'module': 'costad', 'class': 'dict(str, dict(str, object))'}, 'freeform-tags': {'module': 'costad', 'class': 'dict(str, string)'}}, output_type={'module': 'costad', 'class': 'CostAlertSubscription'}) +@cli_util.wrap_exceptions +def update_cost_alert_subscription(ctx, from_json, force, wait_for_state, max_wait_seconds, wait_interval_seconds, subscription_id, description, channels, defined_tags, freeform_tags, if_match): + + if isinstance(subscription_id, six.string_types) and len(subscription_id.strip()) == 0: + raise click.UsageError('Parameter --subscription-id cannot be whitespace or empty string') + if not force: + if defined_tags or freeform_tags: + if not click.confirm("WARNING: Updates to defined-tags and freeform-tags will replace any existing values. Are you sure you want to continue?"): + ctx.abort() + + kwargs = {} + if if_match is not None: + kwargs['if_match'] = if_match + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + + _details = {} + + if description is not None: + _details['description'] = description + + if channels is not None: + _details['channels'] = channels + + if defined_tags is not None: + _details['definedTags'] = cli_util.parse_json_parameter("defined_tags", defined_tags) + + if freeform_tags is not None: + _details['freeformTags'] = cli_util.parse_json_parameter("freeform_tags", freeform_tags) + + client = cli_util.build_client('costad', 'cost_ad', ctx) + result = client.update_cost_alert_subscription( + cost_alert_subscription_id=subscription_id, + update_cost_alert_subscription_details=_details, + **kwargs + ) + if wait_for_state: + + if hasattr(client, 'get_cost_alert_subscription') and callable(getattr(client, 'get_cost_alert_subscription')): + try: + wait_period_kwargs = {} + if max_wait_seconds is not None: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds is not None: + wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + + click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_cost_alert_subscription(result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + except oci.exceptions.MaximumWaitTimeExceeded as e: + # If we fail, we should show an error, but we should still provide the information to the customer + click.echo('Failed to wait until the resource entered the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + sys.exit(2) + except Exception: + click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + raise + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@cost_anomaly_event_group.command(name=cli_util.override('costad.update_cost_anomaly_event.command_name', 'update'), help=u"""Update a CostAnomalyEvent identified by the OCID. \n[Command Reference](updateCostAnomalyEvent)""") +@cli_util.option('--cost-anomaly-event-id', required=True, help=u"""The unique costAnomalyEventId OCID.""") +@cli_util.option('--feedback-response', help=u"""The feedback response for the cost anomaly event.""") +@cli_util.option('--defined-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Defined tags for this resource. Each key is predefined and scoped to a namespace. For more information, see [Resource Tags]. + +Example: `{\"Operations\": {\"CostCenter\": \"42\"}}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--freeform-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Free-form tags for this resource. Each tag is a simple key-value pair with no predefined name, type, or namespace. For more information, see [Resource Tags]. + +Example: `{\"Department\": \"Finance\"}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--if-match', help=u"""For optimistic concurrency control. In the PUT or DELETE call for a resource, set the `if-match` parameter to the value of the etag from a previous GET or POST response for that resource. The resource will be updated or deleted only if the etag you provide matches the resource's current etag value.""") +@cli_util.option('--force', help="""Perform update without prompting for confirmation.""", is_flag=True) +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACTIVE", "INACTIVE"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACTIVE --wait-for-state INACTIVE would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@json_skeleton_utils.get_cli_json_input_option({'defined-tags': {'module': 'costad', 'class': 'dict(str, dict(str, object))'}, 'freeform-tags': {'module': 'costad', 'class': 'dict(str, string)'}}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'defined-tags': {'module': 'costad', 'class': 'dict(str, dict(str, object))'}, 'freeform-tags': {'module': 'costad', 'class': 'dict(str, string)'}}, output_type={'module': 'costad', 'class': 'CostAnomalyEvent'}) +@cli_util.wrap_exceptions +def update_cost_anomaly_event(ctx, from_json, force, wait_for_state, max_wait_seconds, wait_interval_seconds, cost_anomaly_event_id, feedback_response, defined_tags, freeform_tags, if_match): + + if isinstance(cost_anomaly_event_id, six.string_types) and len(cost_anomaly_event_id.strip()) == 0: + raise click.UsageError('Parameter --cost-anomaly-event-id cannot be whitespace or empty string') + if not force: + if defined_tags or freeform_tags: + if not click.confirm("WARNING: Updates to defined-tags and freeform-tags will replace any existing values. Are you sure you want to continue?"): + ctx.abort() + + kwargs = {} + if if_match is not None: + kwargs['if_match'] = if_match + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + + _details = {} + + if feedback_response is not None: + _details['feedbackResponse'] = feedback_response + + if defined_tags is not None: + _details['definedTags'] = cli_util.parse_json_parameter("defined_tags", defined_tags) + + if freeform_tags is not None: + _details['freeformTags'] = cli_util.parse_json_parameter("freeform_tags", freeform_tags) + + client = cli_util.build_client('costad', 'cost_ad', ctx) + result = client.update_cost_anomaly_event( + cost_anomaly_event_id=cost_anomaly_event_id, + update_cost_anomaly_event_details=_details, + **kwargs + ) + if wait_for_state: + + if hasattr(client, 'get_cost_anomaly_event') and callable(getattr(client, 'get_cost_anomaly_event')): + try: + wait_period_kwargs = {} + if max_wait_seconds is not None: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds is not None: + wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + + click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_cost_anomaly_event(result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + except oci.exceptions.MaximumWaitTimeExceeded as e: + # If we fail, we should show an error, but we should still provide the information to the customer + click.echo('Failed to wait until the resource entered the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + sys.exit(2) + except Exception: + click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + raise + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@cost_anomaly_monitor_group.command(name=cli_util.override('costad.update_cost_anomaly_monitor.command_name', 'update'), help=u"""Update a CostAnomalyMonitor identified by the OCID. \n[Command Reference](updateCostAnomalyMonitor)""") +@cli_util.option('--cost-anomaly-monitor-id', required=True, help=u"""The unique costAnomalyMonitor OCID.""") +@cli_util.option('--description', help=u"""The description of the cost anomaly monitor.""") +@cli_util.option('--cost-alert-subscription-map', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--defined-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Defined tags for this resource. Each key is predefined and scoped to a namespace. For more information, see [Resource Tags]. + +Example: `{\"Operations\": {\"CostCenter\": \"42\"}}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--freeform-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Free-form tags for this resource. Each tag is a simple key-value pair with no predefined name, type, or namespace. For more information, see [Resource Tags]. + +Example: `{\"Department\": \"Finance\"}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--if-match', help=u"""For optimistic concurrency control. In the PUT or DELETE call for a resource, set the `if-match` parameter to the value of the etag from a previous GET or POST response for that resource. The resource will be updated or deleted only if the etag you provide matches the resource's current etag value.""") +@cli_util.option('--force', help="""Perform update without prompting for confirmation.""", is_flag=True) +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACTIVE", "INACTIVE", "DELETED"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACTIVE --wait-for-state DELETED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@json_skeleton_utils.get_cli_json_input_option({'cost-alert-subscription-map': {'module': 'costad', 'class': 'CostAlertSubscriptionMap'}, 'defined-tags': {'module': 'costad', 'class': 'dict(str, dict(str, object))'}, 'freeform-tags': {'module': 'costad', 'class': 'dict(str, string)'}}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'cost-alert-subscription-map': {'module': 'costad', 'class': 'CostAlertSubscriptionMap'}, 'defined-tags': {'module': 'costad', 'class': 'dict(str, dict(str, object))'}, 'freeform-tags': {'module': 'costad', 'class': 'dict(str, string)'}}, output_type={'module': 'costad', 'class': 'CostAnomalyMonitor'}) +@cli_util.wrap_exceptions +def update_cost_anomaly_monitor(ctx, from_json, force, wait_for_state, max_wait_seconds, wait_interval_seconds, cost_anomaly_monitor_id, description, cost_alert_subscription_map, defined_tags, freeform_tags, if_match): + + if isinstance(cost_anomaly_monitor_id, six.string_types) and len(cost_anomaly_monitor_id.strip()) == 0: + raise click.UsageError('Parameter --cost-anomaly-monitor-id cannot be whitespace or empty string') + if not force: + if cost_alert_subscription_map or defined_tags or freeform_tags: + if not click.confirm("WARNING: Updates to cost-alert-subscription-map and defined-tags and freeform-tags will replace any existing values. Are you sure you want to continue?"): + ctx.abort() + + kwargs = {} + if if_match is not None: + kwargs['if_match'] = if_match + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + + _details = {} + + if description is not None: + _details['description'] = description + + if cost_alert_subscription_map is not None: + _details['costAlertSubscriptionMap'] = cli_util.parse_json_parameter("cost_alert_subscription_map", cost_alert_subscription_map) + + if defined_tags is not None: + _details['definedTags'] = cli_util.parse_json_parameter("defined_tags", defined_tags) + + if freeform_tags is not None: + _details['freeformTags'] = cli_util.parse_json_parameter("freeform_tags", freeform_tags) + + client = cli_util.build_client('costad', 'cost_ad', ctx) + result = client.update_cost_anomaly_monitor( + cost_anomaly_monitor_id=cost_anomaly_monitor_id, + update_cost_anomaly_monitor_details=_details, + **kwargs + ) + if wait_for_state: + + if hasattr(client, 'get_cost_anomaly_monitor') and callable(getattr(client, 'get_cost_anomaly_monitor')): + try: + wait_period_kwargs = {} + if max_wait_seconds is not None: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds is not None: + wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + + click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_cost_anomaly_monitor(result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + except oci.exceptions.MaximumWaitTimeExceeded as e: + # If we fail, we should show an error, but we should still provide the information to the customer + click.echo('Failed to wait until the resource entered the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + sys.exit(2) + except Exception: + click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + raise + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) diff --git a/services/costad/tests/__init__.py b/services/costad/tests/__init__.py new file mode 100644 index 000000000..bbc084f8d --- /dev/null +++ b/services/costad/tests/__init__.py @@ -0,0 +1,4 @@ +# coding: utf-8 +# Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. +# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. +# NOTE: This class is auto generated by OracleSDKGenerator. DO NOT EDIT. API Version: 20190111 diff --git a/services/costad/tests/util/generated/command_to_api.py b/services/costad/tests/util/generated/command_to_api.py new file mode 100644 index 000000000..717ad65c9 --- /dev/null +++ b/services/costad/tests/util/generated/command_to_api.py @@ -0,0 +1,21 @@ +# coding: utf-8 +# Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. + +SDK_client_map = { + "costad.create_cost_alert_subscription": "oci.costad.CostAdClient.create_cost_alert_subscription", + "costad.create_cost_anomaly_monitor": "oci.costad.CostAdClient.create_cost_anomaly_monitor", + "costad.delete_cost_alert_subscription": "oci.costad.CostAdClient.delete_cost_alert_subscription", + "costad.delete_cost_anomaly_monitor": "oci.costad.CostAdClient.delete_cost_anomaly_monitor", + "costad.disable_cost_anomaly_monitor": "oci.costad.CostAdClient.disable_cost_anomaly_monitor", + "costad.enable_cost_anomaly_monitor": "oci.costad.CostAdClient.enable_cost_anomaly_monitor", + "costad.get_cost_alert_subscription": "oci.costad.CostAdClient.get_cost_alert_subscription", + "costad.get_cost_anomaly_event": "oci.costad.CostAdClient.get_cost_anomaly_event", + "costad.get_cost_anomaly_monitor": "oci.costad.CostAdClient.get_cost_anomaly_monitor", + "costad.list_cost_alert_subscriptions": "oci.costad.CostAdClient.list_cost_alert_subscriptions", + "costad.list_cost_anomaly_events": "oci.costad.CostAdClient.list_cost_anomaly_events", + "costad.list_cost_anomaly_monitors": "oci.costad.CostAdClient.list_cost_anomaly_monitors", + "costad.summarize_cost_anomaly_event_analytics": "oci.costad.CostAdClient.summarize_cost_anomaly_event_analytics", + "costad.update_cost_alert_subscription": "oci.costad.CostAdClient.update_cost_alert_subscription", + "costad.update_cost_anomaly_event": "oci.costad.CostAdClient.update_cost_anomaly_event", + "costad.update_cost_anomaly_monitor": "oci.costad.CostAdClient.update_cost_anomaly_monitor", +} diff --git a/services/database_tools_runtime/src/oci_cli_database_tools_runtime/generated/databasetoolsruntime_cli.py b/services/database_tools_runtime/src/oci_cli_database_tools_runtime/generated/databasetoolsruntime_cli.py index e771c9f55..18d27ff68 100644 --- a/services/database_tools_runtime/src/oci_cli_database_tools_runtime/generated/databasetoolsruntime_cli.py +++ b/services/database_tools_runtime/src/oci_cli_database_tools_runtime/generated/databasetoolsruntime_cli.py @@ -16,7 +16,7 @@ from oci_cli.aliasing import CommandGroupWithAlias -@cli.command(cli_util.override('dbtools_runtime.dbtools_runtime_root_group.command_name', 'dbtools-runtime'), cls=CommandGroupWithAlias, help=cli_util.override('dbtools_runtime.dbtools_runtime_root_group.help', """Use the Database Tools Runtime API to connect to databases through Database Tools Connections."""), short_help=cli_util.override('dbtools_runtime.dbtools_runtime_root_group.short_help', """Database Tools Service Runtime""")) +@cli.command(cli_util.override('dbtools_runtime.dbtools_runtime_root_group.command_name', 'dbtools-runtime'), cls=CommandGroupWithAlias, help=cli_util.override('dbtools_runtime.dbtools_runtime_root_group.help', """Use the Database Tools Runtime API to connect to databases through Database Tools Connections."""), short_help=cli_util.override('dbtools_runtime.dbtools_runtime_root_group.short_help', """Database Tools Runtime API""")) @cli_util.help_option_group def dbtools_runtime_root_group(): pass @@ -2113,7 +2113,7 @@ def list_work_request_logs(ctx, from_json, all_pages, page_size, work_request_id @cli_util.option('--sort-by', type=custom_types.CliCaseInsensitiveChoice(["timeAccepted", "timeUpdated", "timeFinished"]), help=u"""The field to sort by. Only one sort order may be provided. Default order for timeAccepted is descending. If no value is specified timeAccepted is default.""") @cli_util.option('--page', help=u"""The page token representing the page at which to start retrieving results. This is usually retrieved from a previous list call.""") @cli_util.option('--limit', type=click.INT, help=u"""The maximum number of items to return.""") -@cli_util.option('--operation-type', type=custom_types.CliCaseInsensitiveChoice(["EXECUTE_SQL"]), multiple=True, help=u"""The work request operation type.""") +@cli_util.option('--operation-type', type=custom_types.CliCaseInsensitiveChoice(["EXECUTE_SQL", "EXECUTE_SQL_SCHEDULED_DELETION"]), multiple=True, help=u"""The work request operation type.""") @cli_util.option('--created-by-principal-id', help=u"""A filter to return only work requests initiated by the specified principal OCID.""") @cli_util.option('--status', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "FAILED", "SUCCEEDED", "CANCELING", "CANCELED", "WAITING"]), multiple=True, help=u"""A filter to return only work requests with one of the specified status values.""") @cli_util.option('--all', 'all_pages', is_flag=True, help="""Fetches all pages of results. If you provide this option, then you cannot provide the --limit option.""") diff --git a/services/generative_ai_inference/src/oci_cli_generative_ai_inference/generated/generativeaiinference_cli.py b/services/generative_ai_inference/src/oci_cli_generative_ai_inference/generated/generativeaiinference_cli.py index 22371a5d6..7985fef73 100644 --- a/services/generative_ai_inference/src/oci_cli_generative_ai_inference/generated/generativeaiinference_cli.py +++ b/services/generative_ai_inference/src/oci_cli_generative_ai_inference/generated/generativeaiinference_cli.py @@ -46,6 +46,12 @@ def embed_text_result_group(): pass +@click.command(cli_util.override('generative_ai_inference.guardrail_version_collection_group.command_name', 'guardrail-version-collection'), cls=CommandGroupWithAlias, help="""The response containing a list of guardrail system versions.""") +@cli_util.help_option_group +def guardrail_version_collection_group(): + pass + + @click.command(cli_util.override('generative_ai_inference.summarize_text_result_group.command_name', 'summarize-text-result'), cls=CommandGroupWithAlias, help="""Summarize text result to return to caller.""") @cli_util.help_option_group def summarize_text_result_group(): @@ -67,6 +73,7 @@ def chat_result_group(): generative_ai_inference_root_group.add_command(generate_text_result_group) generative_ai_inference_root_group.add_command(apply_guardrails_result_group) generative_ai_inference_root_group.add_command(embed_text_result_group) +generative_ai_inference_root_group.add_command(guardrail_version_collection_group) generative_ai_inference_root_group.add_command(summarize_text_result_group) generative_ai_inference_root_group.add_command(rerank_text_result_group) generative_ai_inference_root_group.add_command(chat_result_group) @@ -76,12 +83,13 @@ def chat_result_group(): @cli_util.option('--input', required=True, type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) @cli_util.option('--guardrail-configs', required=True, type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) @cli_util.option('--compartment-id', required=True, help=u"""The OCID of the compartment to apply guardrails.""") -@json_skeleton_utils.get_cli_json_input_option({'input': {'module': 'generative_ai_inference', 'class': 'GuardrailsInput'}, 'guardrail-configs': {'module': 'generative_ai_inference', 'class': 'GuardrailConfigs'}}) +@cli_util.option('--guardrail-version-config', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@json_skeleton_utils.get_cli_json_input_option({'input': {'module': 'generative_ai_inference', 'class': 'GuardrailsInput'}, 'guardrail-configs': {'module': 'generative_ai_inference', 'class': 'GuardrailConfigs'}, 'guardrail-version-config': {'module': 'generative_ai_inference', 'class': 'GuardrailVersionConfig'}}) @cli_util.help_option @click.pass_context -@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'input': {'module': 'generative_ai_inference', 'class': 'GuardrailsInput'}, 'guardrail-configs': {'module': 'generative_ai_inference', 'class': 'GuardrailConfigs'}}, output_type={'module': 'generative_ai_inference', 'class': 'ApplyGuardrailsResult'}) +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'input': {'module': 'generative_ai_inference', 'class': 'GuardrailsInput'}, 'guardrail-configs': {'module': 'generative_ai_inference', 'class': 'GuardrailConfigs'}, 'guardrail-version-config': {'module': 'generative_ai_inference', 'class': 'GuardrailVersionConfig'}}, output_type={'module': 'generative_ai_inference', 'class': 'ApplyGuardrailsResult'}) @cli_util.wrap_exceptions -def apply_guardrails(ctx, from_json, input, guardrail_configs, compartment_id): +def apply_guardrails(ctx, from_json, input, guardrail_configs, compartment_id, guardrail_version_config): kwargs = {} kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) @@ -91,6 +99,9 @@ def apply_guardrails(ctx, from_json, input, guardrail_configs, compartment_id): _details['guardrailConfigs'] = cli_util.parse_json_parameter("guardrail_configs", guardrail_configs) _details['compartmentId'] = compartment_id + if guardrail_version_config is not None: + _details['guardrailVersionConfig'] = cli_util.parse_json_parameter("guardrail_version_config", guardrail_version_config) + client = cli_util.build_client('generative_ai_inference', 'generative_ai_inference', ctx) result = client.apply_guardrails( apply_guardrails_details=_details, @@ -102,14 +113,15 @@ def apply_guardrails(ctx, from_json, input, guardrail_configs, compartment_id): @apply_guardrails_result_group.command(name=cli_util.override('generative_ai_inference.apply_guardrails_guardrails_text_input.command_name', 'apply-guardrails-guardrails-text-input'), help=u"""Applies guardrails to the input text, including content moderation, PII detection, and prompt injection protection. \n[Command Reference](applyGuardrails)""") @cli_util.option('--guardrail-configs', required=True, type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) @cli_util.option('--compartment-id', required=True, help=u"""The OCID of the compartment to apply guardrails.""") +@cli_util.option('--guardrail-version-config', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) @cli_util.option('--input-content', help=u"""The actual input data.""") @cli_util.option('--input-language-code', help=u"""The language code of the input text. example - en | es | en-US | zh-CN""") -@json_skeleton_utils.get_cli_json_input_option({'guardrail-configs': {'module': 'generative_ai_inference', 'class': 'GuardrailConfigs'}}) +@json_skeleton_utils.get_cli_json_input_option({'guardrail-configs': {'module': 'generative_ai_inference', 'class': 'GuardrailConfigs'}, 'guardrail-version-config': {'module': 'generative_ai_inference', 'class': 'GuardrailVersionConfig'}}) @cli_util.help_option @click.pass_context -@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'guardrail-configs': {'module': 'generative_ai_inference', 'class': 'GuardrailConfigs'}}, output_type={'module': 'generative_ai_inference', 'class': 'ApplyGuardrailsResult'}) +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'guardrail-configs': {'module': 'generative_ai_inference', 'class': 'GuardrailConfigs'}, 'guardrail-version-config': {'module': 'generative_ai_inference', 'class': 'GuardrailVersionConfig'}}, output_type={'module': 'generative_ai_inference', 'class': 'ApplyGuardrailsResult'}) @cli_util.wrap_exceptions -def apply_guardrails_guardrails_text_input(ctx, from_json, guardrail_configs, compartment_id, input_content, input_language_code): +def apply_guardrails_guardrails_text_input(ctx, from_json, guardrail_configs, compartment_id, guardrail_version_config, input_content, input_language_code): kwargs = {} kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) @@ -119,6 +131,9 @@ def apply_guardrails_guardrails_text_input(ctx, from_json, guardrail_configs, co _details['guardrailConfigs'] = cli_util.parse_json_parameter("guardrail_configs", guardrail_configs) _details['compartmentId'] = compartment_id + if guardrail_version_config is not None: + _details['guardrailVersionConfig'] = cli_util.parse_json_parameter("guardrail_version_config", guardrail_version_config) + if input_content is not None: _details['input']['content'] = input_content @@ -1076,6 +1091,57 @@ def generate_text_cohere_llm_inference_request(ctx, from_json, compartment_id, s cli_util.render_response(result, ctx) +@guardrail_version_collection_group.command(name=cli_util.override('generative_ai_inference.list_guardrail_versions.command_name', 'list-guardrail-versions'), help=u"""List the available guardrail system versions. \n[Command Reference](listGuardrailVersions)""") +@cli_util.option('--opc-compartment-id', required=True, help=u"""The client compartment ID.""") +@cli_util.option('--state', type=custom_types.CliCaseInsensitiveChoice(["ACTIVE", "PREVIEW", "DEPRECATED", "RETIRED"]), help=u"""A filter to return only the guardrail versions whose state matches the given value.""") +@cli_util.option('--limit', type=click.INT, help=u"""For list pagination. The maximum number of results per page, or items to return in a paginated \"List\" call. For important details about how pagination works, see [List Pagination].""") +@cli_util.option('--page', help=u"""For list pagination. The value of the opc-next-page response header from the previous \"List\" call. For important details about how pagination works, see [List Pagination].""") +@cli_util.option('--all', 'all_pages', is_flag=True, help="""Fetches all pages of results. If you provide this option, then you cannot provide the --limit option.""") +@cli_util.option('--page-size', type=click.INT, help="""When fetching results, the number of results to fetch per call. Only valid when used with --all or --limit, and ignored otherwise.""") +@json_skeleton_utils.get_cli_json_input_option({}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}, output_type={'module': 'generative_ai_inference', 'class': 'GuardrailVersionCollection'}) +@cli_util.wrap_exceptions +def list_guardrail_versions(ctx, from_json, all_pages, page_size, opc_compartment_id, state, limit, page): + + if all_pages and limit: + raise click.UsageError('If you provide the --all option you cannot provide the --limit option') + + kwargs = {} + if state is not None: + kwargs['state'] = state + if limit is not None: + kwargs['limit'] = limit + if page is not None: + kwargs['page'] = page + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('generative_ai_inference', 'generative_ai_inference', ctx) + if all_pages: + if page_size: + kwargs['limit'] = page_size + + result = cli_util.list_call_get_all_results( + client.list_guardrail_versions, + opc_compartment_id=opc_compartment_id, + **kwargs + ) + elif limit is not None: + result = cli_util.list_call_get_up_to_limit( + client.list_guardrail_versions, + limit, + page_size, + opc_compartment_id=opc_compartment_id, + **kwargs + ) + else: + result = client.list_guardrail_versions( + opc_compartment_id=opc_compartment_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + @rerank_text_result_group.command(name=cli_util.override('generative_ai_inference.rerank_text.command_name', 'rerank-text'), help=u"""Reranks the text responses based on the input documents and a prompt. Rerank assigns an index and a relevance score to each document, indicating which document is most related to the prompt. \n[Command Reference](rerankText)""") diff --git a/services/generative_ai_inference/tests/util/generated/command_to_api.py b/services/generative_ai_inference/tests/util/generated/command_to_api.py index df05f7c33..4c62685d1 100644 --- a/services/generative_ai_inference/tests/util/generated/command_to_api.py +++ b/services/generative_ai_inference/tests/util/generated/command_to_api.py @@ -6,6 +6,7 @@ "generative_ai_inference.chat": "oci.generative_ai_inference.GenerativeAiInferenceClient.chat", "generative_ai_inference.embed_text": "oci.generative_ai_inference.GenerativeAiInferenceClient.embed_text", "generative_ai_inference.generate_text": "oci.generative_ai_inference.GenerativeAiInferenceClient.generate_text", + "generative_ai_inference.list_guardrail_versions": "oci.generative_ai_inference.GenerativeAiInferenceClient.list_guardrail_versions", "generative_ai_inference.rerank_text": "oci.generative_ai_inference.GenerativeAiInferenceClient.rerank_text", "generative_ai_inference.summarize_text": "oci.generative_ai_inference.GenerativeAiInferenceClient.summarize_text", } diff --git a/services/mysql/src/oci_cli_db_system/generated/dbsystem_cli.py b/services/mysql/src/oci_cli_db_system/generated/dbsystem_cli.py index 5dd13c096..57744c83b 100644 --- a/services/mysql/src/oci_cli_db_system/generated/dbsystem_cli.py +++ b/services/mysql/src/oci_cli_db_system/generated/dbsystem_cli.py @@ -409,6 +409,226 @@ def create_db_system(ctx, from_json, wait_for_state, max_wait_seconds, wait_inte cli_util.render_response(result, ctx) +@db_system_group.command(name=cli_util.override('db_system.create_db_system_create_db_system_source_from_db_system_details.command_name', 'create-db-system-create-db-system-source-from-db-system-details'), help=u"""Creates and launches a DB System. \n[Command Reference](createDbSystem)""") +@cli_util.option('--compartment-id', required=True, help=u"""The OCID of the compartment.""") +@cli_util.option('--shape-name', required=True, help=u"""The name of the shape. The shape determines the resources allocated - CPU cores and memory for VM shapes; CPU cores, memory and storage for non-VM (or bare metal) shapes. To get a list of shapes, use the [ListShapes] operation.""") +@cli_util.option('--subnet-id', required=True, help=u"""The OCID of the subnet the DB System is associated with.""") +@cli_util.option('--source-db-system-id', required=True, help=u"""The OCID of the DB system to be used as the source for the new DB System.""") +@cli_util.option('--display-name', help=u"""The user-friendly name for the DB System. It does not have to be unique.""") +@cli_util.option('--description', help=u"""User-provided data about the DB System.""") +@cli_util.option('--rest', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--database-console', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--is-highly-available', type=click.BOOL, help=u"""Specifies if the DB System is highly available. + +When creating a DB System with High Availability, three instances are created and placed according to your region- and subnet-type. The secondaries are placed automatically in the other two availability or fault domains. You can choose the preferred location of your primary instance, only.""") +@cli_util.option('--availability-domain', help=u"""The availability domain on which to deploy the Read/Write endpoint. This defines the preferred primary instance. + +In a failover scenario, the Read/Write endpoint is redirected to one of the other availability domains and the MySQL instance in that domain is promoted to the primary instance. This redirection does not affect the IP address of the DB System in any way. + +For a standalone DB System, this defines the availability domain in which the DB System is placed.""") +@cli_util.option('--fault-domain', help=u"""The fault domain on which to deploy the Read/Write endpoint. This defines the preferred primary instance. + +In a failover scenario, the Read/Write endpoint is redirected to one of the other fault domains and the MySQL instance in that domain is promoted to the primary instance. This redirection does not affect the IP address of the DB System in any way. + +For a standalone DB System, this defines the fault domain in which the DB System is placed.""") +@cli_util.option('--configuration-id', help=u"""The OCID of the Configuration to be used for this DB System.""") +@cli_util.option('--mysql-version', help=u"""The specific MySQL version identifier.""") +@cli_util.option('--nsg-ids', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Network Security Group OCIDs used for the VNIC attachment.""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--security-attributes', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Security Attributes for this resource. Each key is predefined and scoped to a namespace. For more information, see [ZPR Artifacts]. Example: `{\"Oracle-ZPR\": {\"MaxEgressCount\": {\"value\": \"42\", \"mode\": \"audit\"}}}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--admin-username', help=u"""The username for the administrative user.""") +@cli_util.option('--admin-password', help=u"""The password for the administrative user. The password must be between 8 and 32 characters long, and must contain at least 1 numeric character, 1 lowercase character, 1 uppercase character, and 1 special (nonalphanumeric) character.""") +@cli_util.option('--data-storage-size-in-gbs', type=click.INT, help=u"""Initial size of the data volume in GBs that will be created and attached. Keep in mind that this only specifies the size of the database data volume, the log volume for the database will be scaled appropriately with its shape.""") +@cli_util.option('--data-storage', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--hostname-label', help=u"""The hostname for the primary endpoint of the DB System. Used for DNS. + +The value is the hostname portion of the primary private IP's fully qualified domain name (FQDN) (for example, \"dbsystem-1\" in FQDN \"dbsystem-1.subnet123.vcn1.oraclevcn.com\"). + +Must be unique across all VNICs in the subnet and comply with RFC 952 and RFC 1123.""") +@cli_util.option('--ip-address', help=u"""The IP address the DB System is configured to listen on. A private IP address of your choice to assign to the primary endpoint of the DB System. Must be an available IP address within the subnet's CIDR. If you don't specify a value, Oracle automatically assigns a private IP address from the subnet. This should be a \"dotted-quad\" style IPv4 address.""") +@cli_util.option('--port', type=click.INT, help=u"""The port for primary endpoint of the DB System to listen on.""") +@cli_util.option('--port-x', type=click.INT, help=u"""The TCP network port on which X Plugin listens for connections. This is the X Plugin equivalent of port.""") +@cli_util.option('--backup-policy', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--maintenance', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--freeform-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Simple key-value pair applied without any predefined name, type or scope. Exists for cross-compatibility only. Example: `{\"bar-key\": \"value\"}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--defined-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Usage of predefined tag keys. These predefined keys are scoped to namespaces. Example: `{\"foo-namespace\": {\"bar-key\": \"value\"}}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--deletion-policy', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--crash-recovery', type=custom_types.CliCaseInsensitiveChoice(["ENABLED", "DISABLED"]), help=u"""Whether to run the DB System with InnoDB Redo Logs and the Double Write Buffer enabled or disabled, and whether to enable or disable syncing of the Binary Logs.""") +@cli_util.option('--database-management', type=custom_types.CliCaseInsensitiveChoice(["ENABLED", "DISABLED"]), help=u"""Whether to enable monitoring via the Database Management service.""") +@cli_util.option('--secure-connections', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--encrypt-data', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--database-mode', help=u"""The database mode indicating the types of statements that will be allowed to run in the DB system. This mode will apply only to statements run by user connections. Replicated write statements will continue to be allowed regardless of the DatabaseMode. - READ_WRITE (default): allow running read and write statements on the DB system; - READ_ONLY: only allow running read statements on the DB system.""") +@cli_util.option('--access-mode', help=u"""The access mode indicating if the database access will be restricted only to administrators or not: - UNRESTRICTED (default): the access to the database is not restricted; - RESTRICTED: the access will be allowed only to users with specific privileges; RESTRICTED will correspond to setting the MySQL system variable [offline_mode] to ON.""") +@cli_util.option('--customer-contacts', type=custom_types.CLI_COMPLEX_TYPE, help=u"""The list of customer email addresses that receive information from Oracle about the specified OCI DB System resource. Oracle uses these email addresses to send notifications about planned and unplanned software maintenance updates, information about system hardware, and other information needed by administrators. Up to 10 email addresses can be added to the customer contacts for a DB System. + +This option is a JSON list with items of type CustomerContact. For documentation on CustomerContact please see our API reference: https://docs.oracle.com/en-us/iaas/api/#/en/dbsystem/20190415/datatypes/CustomerContact.""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--read-endpoint', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--telemetry-configuration', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--source-region', help=u"""The region identifier of the source region where the DB system exists, only if it is in a different region. If the source DB system is in the same region, then no region must be specified. For more information, please see [Regions and Availability Domains].""") +@cli_util.option('--source-channel', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "FAILED", "SUCCEEDED", "CANCELING", "CANCELED"]), multiple=True, help="""This operation asynchronously creates, modifies or deletes a resource and uses a work request to track the progress of the operation. Specify this option to perform the action and then wait until the work request reaches a certain state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACCEPTED --wait-for-state CANCELED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the work request has reached the state defined by --wait-for-state. Defaults to 30 seconds.""") +@json_skeleton_utils.get_cli_json_input_option({'rest': {'module': 'mysql', 'class': 'CreateRestDetails'}, 'database-console': {'module': 'mysql', 'class': 'CreateDatabaseConsoleDetails'}, 'nsg-ids': {'module': 'mysql', 'class': 'list[string]'}, 'security-attributes': {'module': 'mysql', 'class': 'dict(str, dict(str, object))'}, 'data-storage': {'module': 'mysql', 'class': 'DataStorageDetails'}, 'backup-policy': {'module': 'mysql', 'class': 'CreateBackupPolicyDetails'}, 'maintenance': {'module': 'mysql', 'class': 'CreateMaintenanceDetails'}, 'freeform-tags': {'module': 'mysql', 'class': 'dict(str, string)'}, 'defined-tags': {'module': 'mysql', 'class': 'dict(str, dict(str, object))'}, 'deletion-policy': {'module': 'mysql', 'class': 'CreateDeletionPolicyDetails'}, 'secure-connections': {'module': 'mysql', 'class': 'SecureConnectionDetails'}, 'encrypt-data': {'module': 'mysql', 'class': 'EncryptDataDetails'}, 'customer-contacts': {'module': 'mysql', 'class': 'list[CustomerContact]'}, 'read-endpoint': {'module': 'mysql', 'class': 'CreateReadEndpointDetails'}, 'telemetry-configuration': {'module': 'mysql', 'class': 'CreateTelemetryConfigurationDetails'}, 'source-channel': {'module': 'mysql', 'class': 'CreateDbSystemSourceFromDbSystemChannelDetails'}}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'rest': {'module': 'mysql', 'class': 'CreateRestDetails'}, 'database-console': {'module': 'mysql', 'class': 'CreateDatabaseConsoleDetails'}, 'nsg-ids': {'module': 'mysql', 'class': 'list[string]'}, 'security-attributes': {'module': 'mysql', 'class': 'dict(str, dict(str, object))'}, 'data-storage': {'module': 'mysql', 'class': 'DataStorageDetails'}, 'backup-policy': {'module': 'mysql', 'class': 'CreateBackupPolicyDetails'}, 'maintenance': {'module': 'mysql', 'class': 'CreateMaintenanceDetails'}, 'freeform-tags': {'module': 'mysql', 'class': 'dict(str, string)'}, 'defined-tags': {'module': 'mysql', 'class': 'dict(str, dict(str, object))'}, 'deletion-policy': {'module': 'mysql', 'class': 'CreateDeletionPolicyDetails'}, 'secure-connections': {'module': 'mysql', 'class': 'SecureConnectionDetails'}, 'encrypt-data': {'module': 'mysql', 'class': 'EncryptDataDetails'}, 'customer-contacts': {'module': 'mysql', 'class': 'list[CustomerContact]'}, 'read-endpoint': {'module': 'mysql', 'class': 'CreateReadEndpointDetails'}, 'telemetry-configuration': {'module': 'mysql', 'class': 'CreateTelemetryConfigurationDetails'}, 'source-channel': {'module': 'mysql', 'class': 'CreateDbSystemSourceFromDbSystemChannelDetails'}}, output_type={'module': 'mysql', 'class': 'DbSystem'}) +@cli_util.wrap_exceptions +def create_db_system_create_db_system_source_from_db_system_details(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, compartment_id, shape_name, subnet_id, source_db_system_id, display_name, description, rest, database_console, is_highly_available, availability_domain, fault_domain, configuration_id, mysql_version, nsg_ids, security_attributes, admin_username, admin_password, data_storage_size_in_gbs, data_storage, hostname_label, ip_address, port, port_x, backup_policy, maintenance, freeform_tags, defined_tags, deletion_policy, crash_recovery, database_management, secure_connections, encrypt_data, database_mode, access_mode, customer_contacts, read_endpoint, telemetry_configuration, source_region, source_channel): + + kwargs = {} + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + + _details = {} + _details['source'] = {} + _details['compartmentId'] = compartment_id + _details['shapeName'] = shape_name + _details['subnetId'] = subnet_id + _details['source']['dbSystemId'] = source_db_system_id + + if display_name is not None: + _details['displayName'] = display_name + + if description is not None: + _details['description'] = description + + if rest is not None: + _details['rest'] = cli_util.parse_json_parameter("rest", rest) + + if database_console is not None: + _details['databaseConsole'] = cli_util.parse_json_parameter("database_console", database_console) + + if is_highly_available is not None: + _details['isHighlyAvailable'] = is_highly_available + + if availability_domain is not None: + _details['availabilityDomain'] = availability_domain + + if fault_domain is not None: + _details['faultDomain'] = fault_domain + + if configuration_id is not None: + _details['configurationId'] = configuration_id + + if mysql_version is not None: + _details['mysqlVersion'] = mysql_version + + if nsg_ids is not None: + _details['nsgIds'] = cli_util.parse_json_parameter("nsg_ids", nsg_ids) + + if security_attributes is not None: + _details['securityAttributes'] = cli_util.parse_json_parameter("security_attributes", security_attributes) + + if admin_username is not None: + _details['adminUsername'] = admin_username + + if admin_password is not None: + _details['adminPassword'] = admin_password + + if data_storage_size_in_gbs is not None: + _details['dataStorageSizeInGBs'] = data_storage_size_in_gbs + + if data_storage is not None: + _details['dataStorage'] = cli_util.parse_json_parameter("data_storage", data_storage) + + if hostname_label is not None: + _details['hostnameLabel'] = hostname_label + + if ip_address is not None: + _details['ipAddress'] = ip_address + + if port is not None: + _details['port'] = port + + if port_x is not None: + _details['portX'] = port_x + + if backup_policy is not None: + _details['backupPolicy'] = cli_util.parse_json_parameter("backup_policy", backup_policy) + + if maintenance is not None: + _details['maintenance'] = cli_util.parse_json_parameter("maintenance", maintenance) + + if freeform_tags is not None: + _details['freeformTags'] = cli_util.parse_json_parameter("freeform_tags", freeform_tags) + + if defined_tags is not None: + _details['definedTags'] = cli_util.parse_json_parameter("defined_tags", defined_tags) + + if deletion_policy is not None: + _details['deletionPolicy'] = cli_util.parse_json_parameter("deletion_policy", deletion_policy) + + if crash_recovery is not None: + _details['crashRecovery'] = crash_recovery + + if database_management is not None: + _details['databaseManagement'] = database_management + + if secure_connections is not None: + _details['secureConnections'] = cli_util.parse_json_parameter("secure_connections", secure_connections) + + if encrypt_data is not None: + _details['encryptData'] = cli_util.parse_json_parameter("encrypt_data", encrypt_data) + + if database_mode is not None: + _details['databaseMode'] = database_mode + + if access_mode is not None: + _details['accessMode'] = access_mode + + if customer_contacts is not None: + _details['customerContacts'] = cli_util.parse_json_parameter("customer_contacts", customer_contacts) + + if read_endpoint is not None: + _details['readEndpoint'] = cli_util.parse_json_parameter("read_endpoint", read_endpoint) + + if telemetry_configuration is not None: + _details['telemetryConfiguration'] = cli_util.parse_json_parameter("telemetry_configuration", telemetry_configuration) + + if source_region is not None: + _details['source']['region'] = source_region + + if source_channel is not None: + _details['source']['channel'] = cli_util.parse_json_parameter("source_channel", source_channel) + + _details['source']['sourceType'] = 'DBSYSTEM' + + client = cli_util.build_client('mysql', 'db_system', ctx) + result = client.create_db_system( + create_db_system_details=_details, + **kwargs + ) + if wait_for_state: + + client = cli_util.build_client('mysql', 'work_requests', ctx) + + if hasattr(client, 'get_work_request') and callable(getattr(client, 'get_work_request')): + try: + wait_period_kwargs = {} + if max_wait_seconds is not None: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds is not None: + wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + if 'opc-work-request-id' not in result.headers: + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state') + cli_util.render_response(result, ctx) + return + + click.echo('Action completed. Waiting until the work request has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_work_request(result.headers['opc-work-request-id']), 'status', wait_for_state, **wait_period_kwargs) + except oci.exceptions.MaximumWaitTimeExceeded as e: + # If we fail, we should show an error, but we should still provide the information to the customer + click.echo('Failed to wait until the work request entered the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + sys.exit(2) + except Exception: + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + raise + else: + click.echo('Unable to wait for the work request to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + @db_system_group.command(name=cli_util.override('db_system.create_db_system_create_db_system_source_from_backup_details.command_name', 'create-db-system-create-db-system-source-from-backup-details'), help=u"""Creates and launches a DB System. \n[Command Reference](createDbSystem)""") @cli_util.option('--compartment-id', required=True, help=u"""The OCID of the compartment.""") @cli_util.option('--shape-name', required=True, help=u"""The name of the shape. The shape determines the resources allocated - CPU cores and memory for VM shapes; CPU cores, memory and storage for non-VM (or bare metal) shapes. To get a list of shapes, use the [ListShapes] operation.""") diff --git a/services/object_storage/tests/integ/test_object_storage_bulk_operations.py b/services/object_storage/tests/integ/test_object_storage_bulk_operations.py index 9f3e8f2ea..1f3dc1378 100644 --- a/services/object_storage/tests/integ/test_object_storage_bulk_operations.py +++ b/services/object_storage/tests/integ/test_object_storage_bulk_operations.py @@ -118,7 +118,7 @@ def create_empty_dir_at_path(path): @pytest.fixture(scope='module', autouse=True) def generate_test_data(object_storage_client, test_id): - global bulk_get_object_to_content, bulk_get_bucket_name, root_bulk_put_folder, bulk_put_large_files, bulk_put_mid_sized_files, bulk_put_bucket_name + global bulk_get_bucket_name, root_bulk_put_folder, bulk_put_bucket_name # Create a test bucket create_bucket_request = oci.object_storage.models.CreateBucketDetails() diff --git a/services/object_storage/tests/integ/test_object_storage_sync_download.py b/services/object_storage/tests/integ/test_object_storage_sync_download.py index e377c9dfa..8f6c36d49 100644 --- a/services/object_storage/tests/integ/test_object_storage_sync_download.py +++ b/services/object_storage/tests/integ/test_object_storage_sync_download.py @@ -54,7 +54,7 @@ def set_recorded_variable(test_id_recorded): @pytest.fixture(scope='module', autouse=True) def generate_files_in_remote(object_storage_client, test_id): - global sync_download_bucket_name, sync_download_test_dir, sync_upload_bucket_name, sync_upload_test_dir + global sync_download_bucket_name, sync_download_test_dir, sync_upload_test_dir print('Setting up the test bucket for sync download..') sync_download_bucket_name = 'ObjectStorageSyncDownloadTest_{}'.format(test_id) @@ -920,7 +920,7 @@ def create_new_files_local(path, no_of_files_to_create, with_content=False, exte fh.write(bulk_operation.generate_random_string(bulk_operation.CONTENT_STRING_LENGTH)) new_local_file_set.add(new_file_path.replace(os.sep, '/')) if is_delete_set: - new_local_file_set.add(f'{os.path.join(path,"dir")}/') + new_local_file_set.add(f'{os.path.join(path, "dir")}/') return new_local_file_set diff --git a/services/object_storage/tests/integ/test_object_storage_sync_empty_folder.py b/services/object_storage/tests/integ/test_object_storage_sync_empty_folder.py index 4cad7db0d..86a14f576 100644 --- a/services/object_storage/tests/integ/test_object_storage_sync_empty_folder.py +++ b/services/object_storage/tests/integ/test_object_storage_sync_empty_folder.py @@ -56,17 +56,16 @@ def generate_files_in_local(object_storage_client, test_id): @pytest.fixture(scope='function') def generate_content_in_remote(object_storage_client): - global sync_upload_bucket_name, sync_download_test_dir, sync_upload_bucket_name, sync_upload_test_dir print('Setting up the content in remote') bulk_operation.clear_and_create_new_bucket(object_storage_client, sync_upload_bucket_name, False) for i in range(OBJECTS_TO_CREATE_IN_REMOTE_FOR_SYNC): - object_name = f'{sync_remote_prefixes[i%4]}Object{i}' + object_name = f'{sync_remote_prefixes[i % 4]}Object{i}' object_content = bulk_operation.generate_random_string(bulk_operation.CONTENT_STRING_LENGTH) object_storage_client.put_object(util.NAMESPACE, sync_upload_bucket_name, object_name, object_content) - empty_dir = f'{sync_remote_prefixes[i%4]}Empty{i}/' + empty_dir = f'{sync_remote_prefixes[i % 4]}Empty{i}/' object_storage_client.put_object(util.NAMESPACE, sync_upload_bucket_name, empty_dir, None) yield print("Tearing down remote content..") diff --git a/services/resource_analytics/src/oci_cli_resource_analytics_instance/generated/resourceanalyticsinstance_cli.py b/services/resource_analytics/src/oci_cli_resource_analytics_instance/generated/resourceanalyticsinstance_cli.py index 615d53f0a..32ca32a13 100644 --- a/services/resource_analytics/src/oci_cli_resource_analytics_instance/generated/resourceanalyticsinstance_cli.py +++ b/services/resource_analytics/src/oci_cli_resource_analytics_instance/generated/resourceanalyticsinstance_cli.py @@ -159,6 +159,7 @@ def change_resource_analytics_instance_compartment(ctx, from_json, wait_for_stat @cli_util.option('--nsg-ids', type=custom_types.CLI_COMPLEX_TYPE, help=u"""List of Network Security Group [OCID]'s. Example: `[\"ocid...\", \"ocid...\"]`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--compute-count', type=click.INT, help=u"""The compute amount (CPUs) available to the Autonomous Database.""") @cli_util.option('--license-model', type=custom_types.CliCaseInsensitiveChoice(["LICENSE_INCLUDED", "BRING_YOUR_OWN_LICENSE"]), help=u"""The Oracle license model that applies to the ADW instance.""") @cli_util.option('--freeform-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Free-form tags for this resource. Each tag is a simple key-value pair with no predefined name, type, or namespace. For more information, see [Resource Tags]. @@ -174,7 +175,7 @@ def change_resource_analytics_instance_compartment(ctx, from_json, wait_for_stat @click.pass_context @json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'adw-admin-password': {'module': 'resource_analytics', 'class': 'AdwAdminPasswordDetails'}, 'nsg-ids': {'module': 'resource_analytics', 'class': 'list[string]'}, 'freeform-tags': {'module': 'resource_analytics', 'class': 'dict(str, string)'}, 'defined-tags': {'module': 'resource_analytics', 'class': 'dict(str, dict(str, object))'}}, output_type={'module': 'resource_analytics', 'class': 'ResourceAnalyticsInstance'}) @cli_util.wrap_exceptions -def create_resource_analytics_instance(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, compartment_id, adw_admin_password, subnet_id, display_name, description, is_mutual_tls_required, nsg_ids, license_model, freeform_tags, defined_tags): +def create_resource_analytics_instance(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, compartment_id, adw_admin_password, subnet_id, display_name, description, is_mutual_tls_required, nsg_ids, compute_count, license_model, freeform_tags, defined_tags): kwargs = {} kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) @@ -196,6 +197,9 @@ def create_resource_analytics_instance(ctx, from_json, wait_for_state, max_wait_ if nsg_ids is not None: _details['nsgIds'] = cli_util.parse_json_parameter("nsg_ids", nsg_ids) + if compute_count is not None: + _details['computeCount'] = compute_count + if license_model is not None: _details['licenseModel'] = license_model @@ -250,6 +254,7 @@ def create_resource_analytics_instance(ctx, from_json, wait_for_state, max_wait_ @cli_util.option('--nsg-ids', type=custom_types.CLI_COMPLEX_TYPE, help=u"""List of Network Security Group [OCID]'s. Example: `[\"ocid...\", \"ocid...\"]`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--compute-count', type=click.INT, help=u"""The compute amount (CPUs) available to the Autonomous Database.""") @cli_util.option('--license-model', type=custom_types.CliCaseInsensitiveChoice(["LICENSE_INCLUDED", "BRING_YOUR_OWN_LICENSE"]), help=u"""The Oracle license model that applies to the ADW instance.""") @cli_util.option('--freeform-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Free-form tags for this resource. Each tag is a simple key-value pair with no predefined name, type, or namespace. For more information, see [Resource Tags]. @@ -265,7 +270,7 @@ def create_resource_analytics_instance(ctx, from_json, wait_for_state, max_wait_ @click.pass_context @json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'nsg-ids': {'module': 'resource_analytics', 'class': 'list[string]'}, 'freeform-tags': {'module': 'resource_analytics', 'class': 'dict(str, string)'}, 'defined-tags': {'module': 'resource_analytics', 'class': 'dict(str, dict(str, object))'}}, output_type={'module': 'resource_analytics', 'class': 'ResourceAnalyticsInstance'}) @cli_util.wrap_exceptions -def create_resource_analytics_instance_plain_text_password_details(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, compartment_id, subnet_id, adw_admin_password_password, display_name, description, is_mutual_tls_required, nsg_ids, license_model, freeform_tags, defined_tags): +def create_resource_analytics_instance_plain_text_password_details(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, compartment_id, subnet_id, adw_admin_password_password, display_name, description, is_mutual_tls_required, nsg_ids, compute_count, license_model, freeform_tags, defined_tags): kwargs = {} kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) @@ -288,6 +293,9 @@ def create_resource_analytics_instance_plain_text_password_details(ctx, from_jso if nsg_ids is not None: _details['nsgIds'] = cli_util.parse_json_parameter("nsg_ids", nsg_ids) + if compute_count is not None: + _details['computeCount'] = compute_count + if license_model is not None: _details['licenseModel'] = license_model @@ -344,6 +352,7 @@ def create_resource_analytics_instance_plain_text_password_details(ctx, from_jso @cli_util.option('--nsg-ids', type=custom_types.CLI_COMPLEX_TYPE, help=u"""List of Network Security Group [OCID]'s. Example: `[\"ocid...\", \"ocid...\"]`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@cli_util.option('--compute-count', type=click.INT, help=u"""The compute amount (CPUs) available to the Autonomous Database.""") @cli_util.option('--license-model', type=custom_types.CliCaseInsensitiveChoice(["LICENSE_INCLUDED", "BRING_YOUR_OWN_LICENSE"]), help=u"""The Oracle license model that applies to the ADW instance.""") @cli_util.option('--freeform-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Free-form tags for this resource. Each tag is a simple key-value pair with no predefined name, type, or namespace. For more information, see [Resource Tags]. @@ -359,7 +368,7 @@ def create_resource_analytics_instance_plain_text_password_details(ctx, from_jso @click.pass_context @json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'nsg-ids': {'module': 'resource_analytics', 'class': 'list[string]'}, 'freeform-tags': {'module': 'resource_analytics', 'class': 'dict(str, string)'}, 'defined-tags': {'module': 'resource_analytics', 'class': 'dict(str, dict(str, object))'}}, output_type={'module': 'resource_analytics', 'class': 'ResourceAnalyticsInstance'}) @cli_util.wrap_exceptions -def create_resource_analytics_instance_vault_secret_password_details(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, compartment_id, subnet_id, adw_admin_password_secret_id, display_name, description, is_mutual_tls_required, nsg_ids, license_model, freeform_tags, defined_tags): +def create_resource_analytics_instance_vault_secret_password_details(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, compartment_id, subnet_id, adw_admin_password_secret_id, display_name, description, is_mutual_tls_required, nsg_ids, compute_count, license_model, freeform_tags, defined_tags): kwargs = {} kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) @@ -382,6 +391,9 @@ def create_resource_analytics_instance_vault_secret_password_details(ctx, from_j if nsg_ids is not None: _details['nsgIds'] = cli_util.parse_json_parameter("nsg_ids", nsg_ids) + if compute_count is not None: + _details['computeCount'] = compute_count + if license_model is not None: _details['licenseModel'] = license_model diff --git a/services/rover/tests/unit/test_unit_test_rover_extended.py b/services/rover/tests/unit/test_unit_test_rover_extended.py index 692137116..85fd53ce0 100644 --- a/services/rover/tests/unit/test_unit_test_rover_extended.py +++ b/services/rover/tests/unit/test_unit_test_rover_extended.py @@ -241,7 +241,7 @@ def test_rover(self, mock_client_render_response, mock_client, mock_prompt, mock # The key is the mock object name and the value is a dict of the side effects for key, value in sub_command_def['methods_to_side_effect'].items(): # k is the method to side effect and v is the tuple of {status, headers, data} - if type(value) == dict: + if type(value) is dict: for k, v in value.items(): def method_side_effect(*args, **kwargs): return Response(v[0], v[1], v[2], Request("mock.method", "mock.url")) diff --git a/services/streaming/src/oci_cli_stream_admin/generated/streamadmin_cli.py b/services/streaming/src/oci_cli_stream_admin/generated/streamadmin_cli.py index c1876f791..879f2d21f 100644 --- a/services/streaming/src/oci_cli_stream_admin/generated/streamadmin_cli.py +++ b/services/streaming/src/oci_cli_stream_admin/generated/streamadmin_cli.py @@ -22,6 +22,12 @@ def stream_admin_root_group(): pass +@click.command(cli_util.override('stream_admin.work_request_error_collection_group.command_name', 'work-request-error-collection'), cls=CommandGroupWithAlias, help="""A list of work request errors. Can contain both errors and other information, such as metadata.""") +@cli_util.help_option_group +def work_request_error_collection_group(): + pass + + @click.command(cli_util.override('stream_admin.stream_pool_group.command_name', 'stream-pool'), cls=CommandGroupWithAlias, help="""The details of a stream pool.""") @cli_util.help_option_group def stream_pool_group(): @@ -34,28 +40,53 @@ def stream_group(): pass +@click.command(cli_util.override('stream_admin.work_request_summary_collection_group.command_name', 'work-request-summary-collection'), cls=CommandGroupWithAlias, help="""A list of work requests. Can contain both work requests and other information, such as metadata.""") +@cli_util.help_option_group +def work_request_summary_collection_group(): + pass + + @click.command(cli_util.override('stream_admin.connect_harness_group.command_name', 'connect-harness'), cls=CommandGroupWithAlias, help="""Detailed representation of a connect harness.""") @cli_util.help_option_group def connect_harness_group(): pass +@click.command(cli_util.override('stream_admin.work_request_log_entry_group.command_name', 'work-request-log-entry'), cls=CommandGroupWithAlias, help="""A log message from performing an operation that is tracked by a work request.""") +@cli_util.help_option_group +def work_request_log_entry_group(): + pass + + +@click.command(cli_util.override('stream_admin.work_request_group.command_name', 'work-request'), cls=CommandGroupWithAlias, help="""An asynchronous work request. Work requests help you monitor long-running operations. When you start a long-running operation, the service creates a work request. A work request is an activity log that lets you track each step in the operation's progress. Each work request has an OCID that lets you interact with it programmatically and use it for automation.""") +@cli_util.help_option_group +def work_request_group(): + pass + + streaming_service_cli.streaming_service_group.add_command(stream_admin_root_group) +stream_admin_root_group.add_command(work_request_error_collection_group) stream_admin_root_group.add_command(stream_pool_group) stream_admin_root_group.add_command(stream_group) +stream_admin_root_group.add_command(work_request_summary_collection_group) stream_admin_root_group.add_command(connect_harness_group) +stream_admin_root_group.add_command(work_request_log_entry_group) +stream_admin_root_group.add_command(work_request_group) @connect_harness_group.command(name=cli_util.override('stream_admin.change_connect_harness_compartment.command_name', 'change-compartment'), help=u"""Moves a resource into a different compartment. When provided, If-Match is checked against ETag values of the resource. \n[Command Reference](changeConnectHarnessCompartment)""") @cli_util.option('--connect-harness-id', required=True, help=u"""The OCID of the connect harness.""") @cli_util.option('--compartment-id', required=True, help=u"""The [OCID] of the compartment into which the resource should be moved.""") @cli_util.option('--if-match', help=u"""For optimistic concurrency control. In the PUT or DELETE call for a resource, set the if-match parameter to the value of the etag from a previous GET or POST response for that resource. The resource will be updated or deleted only if the etag you provide matches the resource's current etag value.""") +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "WAITING", "NEEDS_ATTENTION", "FAILED", "SUCCEEDED", "CANCELING", "CANCELED"]), multiple=True, help="""This operation asynchronously creates, modifies or deletes a resource and uses a work request to track the progress of the operation. Specify this option to perform the action and then wait until the work request reaches a certain state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACCEPTED --wait-for-state CANCELED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the work request has reached the state defined by --wait-for-state. Defaults to 30 seconds.""") @json_skeleton_utils.get_cli_json_input_option({}) @cli_util.help_option @click.pass_context @json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}) @cli_util.wrap_exceptions -def change_connect_harness_compartment(ctx, from_json, connect_harness_id, compartment_id, if_match): +def change_connect_harness_compartment(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, connect_harness_id, compartment_id, if_match): if isinstance(connect_harness_id, six.string_types) and len(connect_harness_id.strip()) == 0: raise click.UsageError('Parameter --connect-harness-id cannot be whitespace or empty string') @@ -74,6 +105,33 @@ def change_connect_harness_compartment(ctx, from_json, connect_harness_id, compa change_connect_harness_compartment_details=_details, **kwargs ) + if wait_for_state: + + if hasattr(client, 'get_work_request') and callable(getattr(client, 'get_work_request')): + try: + wait_period_kwargs = {} + if max_wait_seconds is not None: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds is not None: + wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + if 'opc-work-request-id' not in result.headers: + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state') + cli_util.render_response(result, ctx) + return + + click.echo('Action completed. Waiting until the work request has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_work_request(result.headers['opc-work-request-id']), 'status', wait_for_state, **wait_period_kwargs) + except oci.exceptions.MaximumWaitTimeExceeded as e: + # If we fail, we should show an error, but we should still provide the information to the customer + click.echo('Failed to wait until the work request entered the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + sys.exit(2) + except Exception: + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + raise + else: + click.echo('Unable to wait for the work request to enter the specified state', file=sys.stderr) cli_util.render_response(result, ctx) @@ -81,12 +139,15 @@ def change_connect_harness_compartment(ctx, from_json, connect_harness_id, compa @cli_util.option('--stream-id', required=True, help=u"""The OCID of the stream.""") @cli_util.option('--compartment-id', required=True, help=u"""The [OCID] of the compartment into which the resource should be moved.""") @cli_util.option('--if-match', help=u"""For optimistic concurrency control. In the PUT or DELETE call for a resource, set the if-match parameter to the value of the etag from a previous GET or POST response for that resource. The resource will be updated or deleted only if the etag you provide matches the resource's current etag value.""") +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "WAITING", "NEEDS_ATTENTION", "FAILED", "SUCCEEDED", "CANCELING", "CANCELED"]), multiple=True, help="""This operation asynchronously creates, modifies or deletes a resource and uses a work request to track the progress of the operation. Specify this option to perform the action and then wait until the work request reaches a certain state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACCEPTED --wait-for-state CANCELED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the work request has reached the state defined by --wait-for-state. Defaults to 30 seconds.""") @json_skeleton_utils.get_cli_json_input_option({}) @cli_util.help_option @click.pass_context @json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}) @cli_util.wrap_exceptions -def change_stream_compartment(ctx, from_json, stream_id, compartment_id, if_match): +def change_stream_compartment(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, stream_id, compartment_id, if_match): if isinstance(stream_id, six.string_types) and len(stream_id.strip()) == 0: raise click.UsageError('Parameter --stream-id cannot be whitespace or empty string') @@ -105,6 +166,33 @@ def change_stream_compartment(ctx, from_json, stream_id, compartment_id, if_matc change_stream_compartment_details=_details, **kwargs ) + if wait_for_state: + + if hasattr(client, 'get_work_request') and callable(getattr(client, 'get_work_request')): + try: + wait_period_kwargs = {} + if max_wait_seconds is not None: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds is not None: + wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + if 'opc-work-request-id' not in result.headers: + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state') + cli_util.render_response(result, ctx) + return + + click.echo('Action completed. Waiting until the work request has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_work_request(result.headers['opc-work-request-id']), 'status', wait_for_state, **wait_period_kwargs) + except oci.exceptions.MaximumWaitTimeExceeded as e: + # If we fail, we should show an error, but we should still provide the information to the customer + click.echo('Failed to wait until the work request entered the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + sys.exit(2) + except Exception: + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + raise + else: + click.echo('Unable to wait for the work request to enter the specified state', file=sys.stderr) cli_util.render_response(result, ctx) @@ -112,12 +200,15 @@ def change_stream_compartment(ctx, from_json, stream_id, compartment_id, if_matc @cli_util.option('--stream-pool-id', required=True, help=u"""The OCID of the stream pool.""") @cli_util.option('--compartment-id', required=True, help=u"""The [OCID] of the compartment into which the resource should be moved.""") @cli_util.option('--if-match', help=u"""For optimistic concurrency control. In the PUT or DELETE call for a resource, set the if-match parameter to the value of the etag from a previous GET or POST response for that resource. The resource will be updated or deleted only if the etag you provide matches the resource's current etag value.""") +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "WAITING", "NEEDS_ATTENTION", "FAILED", "SUCCEEDED", "CANCELING", "CANCELED"]), multiple=True, help="""This operation asynchronously creates, modifies or deletes a resource and uses a work request to track the progress of the operation. Specify this option to perform the action and then wait until the work request reaches a certain state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACCEPTED --wait-for-state CANCELED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the work request has reached the state defined by --wait-for-state. Defaults to 30 seconds.""") @json_skeleton_utils.get_cli_json_input_option({}) @cli_util.help_option @click.pass_context @json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}) @cli_util.wrap_exceptions -def change_stream_pool_compartment(ctx, from_json, stream_pool_id, compartment_id, if_match): +def change_stream_pool_compartment(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, stream_pool_id, compartment_id, if_match): if isinstance(stream_pool_id, six.string_types) and len(stream_pool_id.strip()) == 0: raise click.UsageError('Parameter --stream-pool-id cannot be whitespace or empty string') @@ -136,6 +227,33 @@ def change_stream_pool_compartment(ctx, from_json, stream_pool_id, compartment_i change_stream_pool_compartment_details=_details, **kwargs ) + if wait_for_state: + + if hasattr(client, 'get_work_request') and callable(getattr(client, 'get_work_request')): + try: + wait_period_kwargs = {} + if max_wait_seconds is not None: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds is not None: + wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + if 'opc-work-request-id' not in result.headers: + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state') + cli_util.render_response(result, ctx) + return + + click.echo('Action completed. Waiting until the work request has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_work_request(result.headers['opc-work-request-id']), 'status', wait_for_state, **wait_period_kwargs) + except oci.exceptions.MaximumWaitTimeExceeded as e: + # If we fail, we should show an error, but we should still provide the information to the customer + click.echo('Failed to wait until the work request entered the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + sys.exit(2) + except Exception: + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state', file=sys.stderr) + cli_util.render_response(result, ctx) + raise + else: + click.echo('Unable to wait for the work request to enter the specified state', file=sys.stderr) cli_util.render_response(result, ctx) @@ -150,9 +268,9 @@ def change_stream_pool_compartment(ctx, from_json, stream_pool_id, compartment_i @cli_util.option('--defined-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Defined tags for this resource. Each key is predefined and scoped to a namespace. For more information, see [Resource Tags]. Example: `{\"Operations\": {\"CostCenter\": \"42\"}}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) -@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED", "UPDATING"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state CREATING --wait-for-state UPDATING would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") -@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") -@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "WAITING", "NEEDS_ATTENTION", "FAILED", "SUCCEEDED", "CANCELING", "CANCELED"]), multiple=True, help="""This operation asynchronously creates, modifies or deletes a resource and uses a work request to track the progress of the operation. Specify this option to perform the action and then wait until the work request reaches a certain state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACCEPTED --wait-for-state CANCELED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the work request has reached the state defined by --wait-for-state. Defaults to 30 seconds.""") @json_skeleton_utils.get_cli_json_input_option({'freeform-tags': {'module': 'streaming', 'class': 'dict(str, string)'}, 'defined-tags': {'module': 'streaming', 'class': 'dict(str, dict(str, object))'}}) @cli_util.help_option @click.pass_context @@ -180,27 +298,31 @@ def create_connect_harness(ctx, from_json, wait_for_state, max_wait_seconds, wai ) if wait_for_state: - if hasattr(client, 'get_connect_harness') and callable(getattr(client, 'get_connect_harness')): + if hasattr(client, 'get_work_request') and callable(getattr(client, 'get_work_request')): try: wait_period_kwargs = {} if max_wait_seconds is not None: wait_period_kwargs['max_wait_seconds'] = max_wait_seconds if wait_interval_seconds is not None: wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + if 'opc-work-request-id' not in result.headers: + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state') + cli_util.render_response(result, ctx) + return - click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) - result = oci.wait_until(client, client.get_connect_harness(result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + click.echo('Action completed. Waiting until the work request has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_work_request(result.headers['opc-work-request-id']), 'status', wait_for_state, **wait_period_kwargs) except oci.exceptions.MaximumWaitTimeExceeded as e: # If we fail, we should show an error, but we should still provide the information to the customer - click.echo('Failed to wait until the resource entered the specified state. Outputting last known resource state', file=sys.stderr) + click.echo('Failed to wait until the work request entered the specified state. Outputting last known resource state', file=sys.stderr) cli_util.render_response(result, ctx) sys.exit(2) except Exception: - click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state', file=sys.stderr) cli_util.render_response(result, ctx) raise else: - click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + click.echo('Unable to wait for the work request to enter the specified state', file=sys.stderr) cli_util.render_response(result, ctx) @@ -218,9 +340,9 @@ def create_connect_harness(ctx, from_json, wait_for_state, max_wait_seconds, wai @cli_util.option('--defined-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Defined tags for this resource. Each key is predefined and scoped to a namespace. For more information, see [Resource Tags]. Example: `{\"Operations\": {\"CostCenter\": \"42\"}}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) -@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED", "UPDATING"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state CREATING --wait-for-state UPDATING would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") -@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") -@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "WAITING", "NEEDS_ATTENTION", "FAILED", "SUCCEEDED", "CANCELING", "CANCELED"]), multiple=True, help="""This operation asynchronously creates, modifies or deletes a resource and uses a work request to track the progress of the operation. Specify this option to perform the action and then wait until the work request reaches a certain state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACCEPTED --wait-for-state CANCELED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the work request has reached the state defined by --wait-for-state. Defaults to 30 seconds.""") @json_skeleton_utils.get_cli_json_input_option({'freeform-tags': {'module': 'streaming', 'class': 'dict(str, string)'}, 'defined-tags': {'module': 'streaming', 'class': 'dict(str, dict(str, object))'}}) @cli_util.help_option @click.pass_context @@ -257,27 +379,31 @@ def create_stream(ctx, from_json, wait_for_state, max_wait_seconds, wait_interva ) if wait_for_state: - if hasattr(client, 'get_stream') and callable(getattr(client, 'get_stream')): + if hasattr(client, 'get_work_request') and callable(getattr(client, 'get_work_request')): try: wait_period_kwargs = {} if max_wait_seconds is not None: wait_period_kwargs['max_wait_seconds'] = max_wait_seconds if wait_interval_seconds is not None: wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + if 'opc-work-request-id' not in result.headers: + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state') + cli_util.render_response(result, ctx) + return - click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) - result = oci.wait_until(client, client.get_stream(result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + click.echo('Action completed. Waiting until the work request has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_work_request(result.headers['opc-work-request-id']), 'status', wait_for_state, **wait_period_kwargs) except oci.exceptions.MaximumWaitTimeExceeded as e: # If we fail, we should show an error, but we should still provide the information to the customer - click.echo('Failed to wait until the resource entered the specified state. Outputting last known resource state', file=sys.stderr) + click.echo('Failed to wait until the work request entered the specified state. Outputting last known resource state', file=sys.stderr) cli_util.render_response(result, ctx) sys.exit(2) except Exception: - click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state', file=sys.stderr) cli_util.render_response(result, ctx) raise else: - click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + click.echo('Unable to wait for the work request to enter the specified state', file=sys.stderr) cli_util.render_response(result, ctx) @@ -298,9 +424,9 @@ def create_stream(ctx, from_json, wait_for_state, max_wait_seconds, wait_interva @cli_util.option('--defined-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Defined tags for this resource. Each key is predefined and scoped to a namespace. For more information, see [Resource Tags]. Example: `{\"Operations\": {\"CostCenter\": \"42\"}}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) -@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED", "UPDATING"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state CREATING --wait-for-state UPDATING would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") -@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") -@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "WAITING", "NEEDS_ATTENTION", "FAILED", "SUCCEEDED", "CANCELING", "CANCELED"]), multiple=True, help="""This operation asynchronously creates, modifies or deletes a resource and uses a work request to track the progress of the operation. Specify this option to perform the action and then wait until the work request reaches a certain state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACCEPTED --wait-for-state CANCELED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the work request has reached the state defined by --wait-for-state. Defaults to 30 seconds.""") @json_skeleton_utils.get_cli_json_input_option({'kafka-settings': {'module': 'streaming', 'class': 'KafkaSettings'}, 'custom-encryption-key-details': {'module': 'streaming', 'class': 'CustomEncryptionKeyDetails'}, 'private-endpoint-details': {'module': 'streaming', 'class': 'PrivateEndpointDetails'}, 'freeform-tags': {'module': 'streaming', 'class': 'dict(str, string)'}, 'security-attributes': {'module': 'streaming', 'class': 'dict(str, dict(str, object))'}, 'defined-tags': {'module': 'streaming', 'class': 'dict(str, dict(str, object))'}}) @cli_util.help_option @click.pass_context @@ -340,27 +466,31 @@ def create_stream_pool(ctx, from_json, wait_for_state, max_wait_seconds, wait_in ) if wait_for_state: - if hasattr(client, 'get_stream_pool') and callable(getattr(client, 'get_stream_pool')): + if hasattr(client, 'get_work_request') and callable(getattr(client, 'get_work_request')): try: wait_period_kwargs = {} if max_wait_seconds is not None: wait_period_kwargs['max_wait_seconds'] = max_wait_seconds if wait_interval_seconds is not None: wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + if 'opc-work-request-id' not in result.headers: + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state') + cli_util.render_response(result, ctx) + return - click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) - result = oci.wait_until(client, client.get_stream_pool(result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + click.echo('Action completed. Waiting until the work request has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_work_request(result.headers['opc-work-request-id']), 'status', wait_for_state, **wait_period_kwargs) except oci.exceptions.MaximumWaitTimeExceeded as e: # If we fail, we should show an error, but we should still provide the information to the customer - click.echo('Failed to wait until the resource entered the specified state. Outputting last known resource state', file=sys.stderr) + click.echo('Failed to wait until the work request entered the specified state. Outputting last known resource state', file=sys.stderr) cli_util.render_response(result, ctx) sys.exit(2) except Exception: - click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state', file=sys.stderr) cli_util.render_response(result, ctx) raise else: - click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + click.echo('Unable to wait for the work request to enter the specified state', file=sys.stderr) cli_util.render_response(result, ctx) @@ -368,9 +498,9 @@ def create_stream_pool(ctx, from_json, wait_for_state, max_wait_seconds, wait_in @cli_util.option('--connect-harness-id', required=True, help=u"""The OCID of the connect harness.""") @cli_util.option('--if-match', help=u"""For optimistic concurrency control. In the PUT or DELETE call for a resource, set the if-match parameter to the value of the etag from a previous GET or POST response for that resource. The resource will be updated or deleted only if the etag you provide matches the resource's current etag value.""") @cli_util.confirm_delete_option -@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED", "UPDATING"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state CREATING --wait-for-state UPDATING would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") -@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") -@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "WAITING", "NEEDS_ATTENTION", "FAILED", "SUCCEEDED", "CANCELING", "CANCELED"]), multiple=True, help="""This operation asynchronously creates, modifies or deletes a resource and uses a work request to track the progress of the operation. Specify this option to perform the action and then wait until the work request reaches a certain state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACCEPTED --wait-for-state CANCELED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the work request has reached the state defined by --wait-for-state. Defaults to 30 seconds.""") @json_skeleton_utils.get_cli_json_input_option({}) @cli_util.help_option @click.pass_context @@ -392,39 +522,31 @@ def delete_connect_harness(ctx, from_json, wait_for_state, max_wait_seconds, wai ) if wait_for_state: - if hasattr(client, 'get_connect_harness') and callable(getattr(client, 'get_connect_harness')): + if hasattr(client, 'get_work_request') and callable(getattr(client, 'get_work_request')): try: wait_period_kwargs = {} if max_wait_seconds is not None: wait_period_kwargs['max_wait_seconds'] = max_wait_seconds if wait_interval_seconds is not None: wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + if 'opc-work-request-id' not in result.headers: + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state') + cli_util.render_response(result, ctx) + return - click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) - oci.wait_until(client, client.get_connect_harness(connect_harness_id), 'lifecycle_state', wait_for_state, succeed_on_not_found=True, **wait_period_kwargs) - except oci.exceptions.ServiceError as e: - # We make an initial service call so we can pass the result to oci.wait_until(), however if we are waiting on the - # outcome of a delete operation it is possible that the resource is already gone and so the initial service call - # will result in an exception that reflects a HTTP 404. In this case, we can exit with success (rather than raising - # the exception) since this would have been the behaviour in the waiter anyway (as for delete we provide the argument - # succeed_on_not_found=True to the waiter). - # - # Any non-404 should still result in the exception being thrown. - if e.status == 404: - pass - else: - raise + click.echo('Action completed. Waiting until the work request has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_work_request(result.headers['opc-work-request-id']), 'status', wait_for_state, **wait_period_kwargs) except oci.exceptions.MaximumWaitTimeExceeded as e: # If we fail, we should show an error, but we should still provide the information to the customer - click.echo('Failed to wait until the resource entered the specified state. Please retrieve the resource to find its current state', file=sys.stderr) + click.echo('Failed to wait until the work request entered the specified state. Please retrieve the work request to find its current state', file=sys.stderr) cli_util.render_response(result, ctx) sys.exit(2) except Exception: - click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state', file=sys.stderr) cli_util.render_response(result, ctx) raise else: - click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + click.echo('Unable to wait for the work request to enter the specified state', file=sys.stderr) cli_util.render_response(result, ctx) @@ -432,9 +554,9 @@ def delete_connect_harness(ctx, from_json, wait_for_state, max_wait_seconds, wai @cli_util.option('--stream-id', required=True, help=u"""The OCID of the stream.""") @cli_util.option('--if-match', help=u"""For optimistic concurrency control. In the PUT or DELETE call for a resource, set the if-match parameter to the value of the etag from a previous GET or POST response for that resource. The resource will be updated or deleted only if the etag you provide matches the resource's current etag value.""") @cli_util.confirm_delete_option -@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED", "UPDATING"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state CREATING --wait-for-state UPDATING would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") -@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") -@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "WAITING", "NEEDS_ATTENTION", "FAILED", "SUCCEEDED", "CANCELING", "CANCELED"]), multiple=True, help="""This operation asynchronously creates, modifies or deletes a resource and uses a work request to track the progress of the operation. Specify this option to perform the action and then wait until the work request reaches a certain state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACCEPTED --wait-for-state CANCELED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the work request has reached the state defined by --wait-for-state. Defaults to 30 seconds.""") @json_skeleton_utils.get_cli_json_input_option({}) @cli_util.help_option @click.pass_context @@ -456,39 +578,31 @@ def delete_stream(ctx, from_json, wait_for_state, max_wait_seconds, wait_interva ) if wait_for_state: - if hasattr(client, 'get_stream') and callable(getattr(client, 'get_stream')): + if hasattr(client, 'get_work_request') and callable(getattr(client, 'get_work_request')): try: wait_period_kwargs = {} if max_wait_seconds is not None: wait_period_kwargs['max_wait_seconds'] = max_wait_seconds if wait_interval_seconds is not None: wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + if 'opc-work-request-id' not in result.headers: + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state') + cli_util.render_response(result, ctx) + return - click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) - oci.wait_until(client, client.get_stream(stream_id), 'lifecycle_state', wait_for_state, succeed_on_not_found=True, **wait_period_kwargs) - except oci.exceptions.ServiceError as e: - # We make an initial service call so we can pass the result to oci.wait_until(), however if we are waiting on the - # outcome of a delete operation it is possible that the resource is already gone and so the initial service call - # will result in an exception that reflects a HTTP 404. In this case, we can exit with success (rather than raising - # the exception) since this would have been the behaviour in the waiter anyway (as for delete we provide the argument - # succeed_on_not_found=True to the waiter). - # - # Any non-404 should still result in the exception being thrown. - if e.status == 404: - pass - else: - raise + click.echo('Action completed. Waiting until the work request has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_work_request(result.headers['opc-work-request-id']), 'status', wait_for_state, **wait_period_kwargs) except oci.exceptions.MaximumWaitTimeExceeded as e: # If we fail, we should show an error, but we should still provide the information to the customer - click.echo('Failed to wait until the resource entered the specified state. Please retrieve the resource to find its current state', file=sys.stderr) + click.echo('Failed to wait until the work request entered the specified state. Please retrieve the work request to find its current state', file=sys.stderr) cli_util.render_response(result, ctx) sys.exit(2) except Exception: - click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state', file=sys.stderr) cli_util.render_response(result, ctx) raise else: - click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + click.echo('Unable to wait for the work request to enter the specified state', file=sys.stderr) cli_util.render_response(result, ctx) @@ -496,9 +610,9 @@ def delete_stream(ctx, from_json, wait_for_state, max_wait_seconds, wait_interva @cli_util.option('--stream-pool-id', required=True, help=u"""The OCID of the stream pool.""") @cli_util.option('--if-match', help=u"""For optimistic concurrency control. In the PUT or DELETE call for a resource, set the if-match parameter to the value of the etag from a previous GET or POST response for that resource. The resource will be updated or deleted only if the etag you provide matches the resource's current etag value.""") @cli_util.confirm_delete_option -@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED", "UPDATING"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state CREATING --wait-for-state UPDATING would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") -@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") -@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "WAITING", "NEEDS_ATTENTION", "FAILED", "SUCCEEDED", "CANCELING", "CANCELED"]), multiple=True, help="""This operation asynchronously creates, modifies or deletes a resource and uses a work request to track the progress of the operation. Specify this option to perform the action and then wait until the work request reaches a certain state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACCEPTED --wait-for-state CANCELED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the work request has reached the state defined by --wait-for-state. Defaults to 30 seconds.""") @json_skeleton_utils.get_cli_json_input_option({}) @cli_util.help_option @click.pass_context @@ -520,39 +634,31 @@ def delete_stream_pool(ctx, from_json, wait_for_state, max_wait_seconds, wait_in ) if wait_for_state: - if hasattr(client, 'get_stream_pool') and callable(getattr(client, 'get_stream_pool')): + if hasattr(client, 'get_work_request') and callable(getattr(client, 'get_work_request')): try: wait_period_kwargs = {} if max_wait_seconds is not None: wait_period_kwargs['max_wait_seconds'] = max_wait_seconds if wait_interval_seconds is not None: wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + if 'opc-work-request-id' not in result.headers: + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state') + cli_util.render_response(result, ctx) + return - click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) - oci.wait_until(client, client.get_stream_pool(stream_pool_id), 'lifecycle_state', wait_for_state, succeed_on_not_found=True, **wait_period_kwargs) - except oci.exceptions.ServiceError as e: - # We make an initial service call so we can pass the result to oci.wait_until(), however if we are waiting on the - # outcome of a delete operation it is possible that the resource is already gone and so the initial service call - # will result in an exception that reflects a HTTP 404. In this case, we can exit with success (rather than raising - # the exception) since this would have been the behaviour in the waiter anyway (as for delete we provide the argument - # succeed_on_not_found=True to the waiter). - # - # Any non-404 should still result in the exception being thrown. - if e.status == 404: - pass - else: - raise + click.echo('Action completed. Waiting until the work request has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_work_request(result.headers['opc-work-request-id']), 'status', wait_for_state, **wait_period_kwargs) except oci.exceptions.MaximumWaitTimeExceeded as e: # If we fail, we should show an error, but we should still provide the information to the customer - click.echo('Failed to wait until the resource entered the specified state. Please retrieve the resource to find its current state', file=sys.stderr) + click.echo('Failed to wait until the work request entered the specified state. Please retrieve the work request to find its current state', file=sys.stderr) cli_util.render_response(result, ctx) sys.exit(2) except Exception: - click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state', file=sys.stderr) cli_util.render_response(result, ctx) raise else: - click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + click.echo('Unable to wait for the work request to enter the specified state', file=sys.stderr) cli_util.render_response(result, ctx) @@ -622,6 +728,28 @@ def get_stream_pool(ctx, from_json, stream_pool_id): cli_util.render_response(result, ctx) +@work_request_group.command(name=cli_util.override('stream_admin.get_work_request.command_name', 'get'), help=u"""Gets the details of a work request. \n[Command Reference](getWorkRequest)""") +@cli_util.option('--work-request-id', required=True, help=u"""The [OCID] of the asynchronous work request.""") +@json_skeleton_utils.get_cli_json_input_option({}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}, output_type={'module': 'streaming', 'class': 'WorkRequest'}) +@cli_util.wrap_exceptions +def get_work_request(ctx, from_json, work_request_id): + + if isinstance(work_request_id, six.string_types) and len(work_request_id.strip()) == 0: + raise click.UsageError('Parameter --work-request-id cannot be whitespace or empty string') + + kwargs = {} + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('streaming', 'stream_admin', ctx) + result = client.get_work_request( + work_request_id=work_request_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + @connect_harness_group.command(name=cli_util.override('stream_admin.list_connect_harnesses.command_name', 'list'), help=u"""Lists the connectharness. \n[Command Reference](listConnectHarnesses)""") @cli_util.option('--compartment-id', required=True, help=u"""The OCID of the compartment.""") @cli_util.option('--id', help=u"""A filter to return only resources that match the given ID exactly.""") @@ -813,6 +941,179 @@ def list_streams(ctx, from_json, all_pages, page_size, compartment_id, stream_po cli_util.render_response(result, ctx) +@work_request_error_collection_group.command(name=cli_util.override('stream_admin.list_work_request_errors.command_name', 'list-work-request-errors'), help=u"""Lists the errors for a work request. \n[Command Reference](listWorkRequestErrors)""") +@cli_util.option('--work-request-id', required=True, help=u"""The [OCID] of the asynchronous work request.""") +@cli_util.option('--page', help=u"""The page at which to start retrieving results.""") +@cli_util.option('--limit', type=click.INT, help=u"""The maximum number of items to return. The value must be between 1 and 50. The default is 10.""") +@cli_util.option('--sort-order', type=custom_types.CliCaseInsensitiveChoice(["ASC", "DESC"]), help=u"""The sort order to use, either 'asc' or 'desc'.""") +@cli_util.option('--sort-by', type=custom_types.CliCaseInsensitiveChoice(["TIMEACCEPTED"]), help=u"""The field to sort by. Only one sort order may be provided. Default order for `timeAccepted` is descending.""") +@cli_util.option('--all', 'all_pages', is_flag=True, help="""Fetches all pages of results. If you provide this option, then you cannot provide the --limit option.""") +@cli_util.option('--page-size', type=click.INT, help="""When fetching results, the number of results to fetch per call. Only valid when used with --all or --limit, and ignored otherwise.""") +@json_skeleton_utils.get_cli_json_input_option({}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}, output_type={'module': 'streaming', 'class': 'WorkRequestErrorCollection'}) +@cli_util.wrap_exceptions +def list_work_request_errors(ctx, from_json, all_pages, page_size, work_request_id, page, limit, sort_order, sort_by): + + if all_pages and limit: + raise click.UsageError('If you provide the --all option you cannot provide the --limit option') + + if isinstance(work_request_id, six.string_types) and len(work_request_id.strip()) == 0: + raise click.UsageError('Parameter --work-request-id cannot be whitespace or empty string') + + kwargs = {} + if page is not None: + kwargs['page'] = page + if limit is not None: + kwargs['limit'] = limit + if sort_order is not None: + kwargs['sort_order'] = sort_order + if sort_by is not None: + kwargs['sort_by'] = sort_by + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('streaming', 'stream_admin', ctx) + if all_pages: + if page_size: + kwargs['limit'] = page_size + + result = cli_util.list_call_get_all_results( + client.list_work_request_errors, + work_request_id=work_request_id, + **kwargs + ) + elif limit is not None: + result = cli_util.list_call_get_up_to_limit( + client.list_work_request_errors, + limit, + page_size, + work_request_id=work_request_id, + **kwargs + ) + else: + result = client.list_work_request_errors( + work_request_id=work_request_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@work_request_log_entry_group.command(name=cli_util.override('stream_admin.list_work_request_logs.command_name', 'list-work-request-logs'), help=u"""Lists the logs for a work request. \n[Command Reference](listWorkRequestLogs)""") +@cli_util.option('--work-request-id', required=True, help=u"""The [OCID] of the asynchronous work request.""") +@cli_util.option('--page', help=u"""The page at which to start retrieving results.""") +@cli_util.option('--limit', type=click.INT, help=u"""The maximum number of items to return. The value must be between 1 and 50. The default is 10.""") +@cli_util.option('--sort-order', type=custom_types.CliCaseInsensitiveChoice(["ASC", "DESC"]), help=u"""The sort order to use, either 'asc' or 'desc'.""") +@cli_util.option('--sort-by', type=custom_types.CliCaseInsensitiveChoice(["TIMEACCEPTED"]), help=u"""The field to sort by. Only one sort order may be provided. Default order for `timeAccepted` is descending.""") +@cli_util.option('--all', 'all_pages', is_flag=True, help="""Fetches all pages of results. If you provide this option, then you cannot provide the --limit option.""") +@cli_util.option('--page-size', type=click.INT, help="""When fetching results, the number of results to fetch per call. Only valid when used with --all or --limit, and ignored otherwise.""") +@json_skeleton_utils.get_cli_json_input_option({}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}, output_type={'module': 'streaming', 'class': 'WorkRequestLogEntryCollection'}) +@cli_util.wrap_exceptions +def list_work_request_logs(ctx, from_json, all_pages, page_size, work_request_id, page, limit, sort_order, sort_by): + + if all_pages and limit: + raise click.UsageError('If you provide the --all option you cannot provide the --limit option') + + if isinstance(work_request_id, six.string_types) and len(work_request_id.strip()) == 0: + raise click.UsageError('Parameter --work-request-id cannot be whitespace or empty string') + + kwargs = {} + if page is not None: + kwargs['page'] = page + if limit is not None: + kwargs['limit'] = limit + if sort_order is not None: + kwargs['sort_order'] = sort_order + if sort_by is not None: + kwargs['sort_by'] = sort_by + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('streaming', 'stream_admin', ctx) + if all_pages: + if page_size: + kwargs['limit'] = page_size + + result = cli_util.list_call_get_all_results( + client.list_work_request_logs, + work_request_id=work_request_id, + **kwargs + ) + elif limit is not None: + result = cli_util.list_call_get_up_to_limit( + client.list_work_request_logs, + limit, + page_size, + work_request_id=work_request_id, + **kwargs + ) + else: + result = client.list_work_request_logs( + work_request_id=work_request_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@work_request_summary_collection_group.command(name=cli_util.override('stream_admin.list_work_requests.command_name', 'list-work-requests'), help=u"""Lists the work requests in a compartment. \n[Command Reference](listWorkRequests)""") +@cli_util.option('--work-request-id', help=u"""The [OCID] of the asynchronous work request.""") +@cli_util.option('--compartment-id', help=u"""The OCID of the compartment. Is exclusive with the `streamPoolId` parameter. One of them is required.""") +@cli_util.option('--page', help=u"""The page at which to start retrieving results.""") +@cli_util.option('--limit', type=click.INT, help=u"""The maximum number of items to return. The value must be between 1 and 50. The default is 10.""") +@cli_util.option('--sort-order', type=custom_types.CliCaseInsensitiveChoice(["ASC", "DESC"]), help=u"""The sort order to use, either 'asc' or 'desc'.""") +@cli_util.option('--sort-by', type=custom_types.CliCaseInsensitiveChoice(["TIMEACCEPTED"]), help=u"""The field to sort by. Only one sort order may be provided. Default order for `timeAccepted` is descending.""") +@cli_util.option('--resource-id', help=u"""The [OCID] of the resource affected by the work request.""") +@cli_util.option('--all', 'all_pages', is_flag=True, help="""Fetches all pages of results. If you provide this option, then you cannot provide the --limit option.""") +@cli_util.option('--page-size', type=click.INT, help="""When fetching results, the number of results to fetch per call. Only valid when used with --all or --limit, and ignored otherwise.""") +@json_skeleton_utils.get_cli_json_input_option({}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}, output_type={'module': 'streaming', 'class': 'WorkRequestSummaryCollection'}) +@cli_util.wrap_exceptions +def list_work_requests(ctx, from_json, all_pages, page_size, work_request_id, compartment_id, page, limit, sort_order, sort_by, resource_id): + + if all_pages and limit: + raise click.UsageError('If you provide the --all option you cannot provide the --limit option') + + kwargs = {} + if work_request_id is not None: + kwargs['work_request_id'] = work_request_id + if compartment_id is not None: + kwargs['compartment_id'] = compartment_id + if page is not None: + kwargs['page'] = page + if limit is not None: + kwargs['limit'] = limit + if sort_order is not None: + kwargs['sort_order'] = sort_order + if sort_by is not None: + kwargs['sort_by'] = sort_by + if resource_id is not None: + kwargs['resource_id'] = resource_id + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('streaming', 'stream_admin', ctx) + if all_pages: + if page_size: + kwargs['limit'] = page_size + + result = cli_util.list_call_get_all_results( + client.list_work_requests, + **kwargs + ) + elif limit is not None: + result = cli_util.list_call_get_up_to_limit( + client.list_work_requests, + limit, + page_size, + **kwargs + ) + else: + result = client.list_work_requests( + **kwargs + ) + cli_util.render_response(result, ctx) + + @connect_harness_group.command(name=cli_util.override('stream_admin.update_connect_harness.command_name', 'update'), help=u"""Updates the tags applied to the connect harness. \n[Command Reference](updateConnectHarness)""") @cli_util.option('--connect-harness-id', required=True, help=u"""The OCID of the connect harness.""") @cli_util.option('--freeform-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Free-form tags for this resource. Each tag is a simple key-value pair that is applied with no predefined name, type, or namespace. Exists for cross-compatibility only. For more information, see [Resource Tags]. @@ -823,9 +1124,9 @@ def list_streams(ctx, from_json, all_pages, page_size, compartment_id, stream_po Example: `{\"Operations\": {\"CostCenter\": \"42\"}}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) @cli_util.option('--if-match', help=u"""For optimistic concurrency control. In the PUT or DELETE call for a resource, set the if-match parameter to the value of the etag from a previous GET or POST response for that resource. The resource will be updated or deleted only if the etag you provide matches the resource's current etag value.""") @cli_util.option('--force', help="""Perform update without prompting for confirmation.""", is_flag=True) -@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED", "UPDATING"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state CREATING --wait-for-state UPDATING would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") -@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") -@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "WAITING", "NEEDS_ATTENTION", "FAILED", "SUCCEEDED", "CANCELING", "CANCELED"]), multiple=True, help="""This operation asynchronously creates, modifies or deletes a resource and uses a work request to track the progress of the operation. Specify this option to perform the action and then wait until the work request reaches a certain state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACCEPTED --wait-for-state CANCELED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the work request has reached the state defined by --wait-for-state. Defaults to 30 seconds.""") @json_skeleton_utils.get_cli_json_input_option({'freeform-tags': {'module': 'streaming', 'class': 'dict(str, string)'}, 'defined-tags': {'module': 'streaming', 'class': 'dict(str, dict(str, object))'}}) @cli_util.help_option @click.pass_context @@ -861,27 +1162,31 @@ def update_connect_harness(ctx, from_json, force, wait_for_state, max_wait_secon ) if wait_for_state: - if hasattr(client, 'get_connect_harness') and callable(getattr(client, 'get_connect_harness')): + if hasattr(client, 'get_work_request') and callable(getattr(client, 'get_work_request')): try: wait_period_kwargs = {} if max_wait_seconds is not None: wait_period_kwargs['max_wait_seconds'] = max_wait_seconds if wait_interval_seconds is not None: wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + if 'opc-work-request-id' not in result.headers: + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state') + cli_util.render_response(result, ctx) + return - click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) - result = oci.wait_until(client, client.get_connect_harness(result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + click.echo('Action completed. Waiting until the work request has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_work_request(result.headers['opc-work-request-id']), 'status', wait_for_state, **wait_period_kwargs) except oci.exceptions.MaximumWaitTimeExceeded as e: # If we fail, we should show an error, but we should still provide the information to the customer - click.echo('Failed to wait until the resource entered the specified state. Outputting last known resource state', file=sys.stderr) + click.echo('Failed to wait until the work request entered the specified state. Outputting last known resource state', file=sys.stderr) cli_util.render_response(result, ctx) sys.exit(2) except Exception: - click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state', file=sys.stderr) cli_util.render_response(result, ctx) raise else: - click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + click.echo('Unable to wait for the work request to enter the specified state', file=sys.stderr) cli_util.render_response(result, ctx) @@ -896,9 +1201,9 @@ def update_connect_harness(ctx, from_json, force, wait_for_state, max_wait_secon Example: `{\"Operations\": {\"CostCenter\": \"42\"}}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) @cli_util.option('--if-match', help=u"""For optimistic concurrency control. In the PUT or DELETE call for a resource, set the if-match parameter to the value of the etag from a previous GET or POST response for that resource. The resource will be updated or deleted only if the etag you provide matches the resource's current etag value.""") @cli_util.option('--force', help="""Perform update without prompting for confirmation.""", is_flag=True) -@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED", "UPDATING"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state CREATING --wait-for-state UPDATING would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") -@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") -@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "WAITING", "NEEDS_ATTENTION", "FAILED", "SUCCEEDED", "CANCELING", "CANCELED"]), multiple=True, help="""This operation asynchronously creates, modifies or deletes a resource and uses a work request to track the progress of the operation. Specify this option to perform the action and then wait until the work request reaches a certain state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACCEPTED --wait-for-state CANCELED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the work request has reached the state defined by --wait-for-state. Defaults to 30 seconds.""") @json_skeleton_utils.get_cli_json_input_option({'freeform-tags': {'module': 'streaming', 'class': 'dict(str, string)'}, 'defined-tags': {'module': 'streaming', 'class': 'dict(str, dict(str, object))'}}) @cli_util.help_option @click.pass_context @@ -937,33 +1242,39 @@ def update_stream(ctx, from_json, force, wait_for_state, max_wait_seconds, wait_ ) if wait_for_state: - if hasattr(client, 'get_stream') and callable(getattr(client, 'get_stream')): + if hasattr(client, 'get_work_request') and callable(getattr(client, 'get_work_request')): try: wait_period_kwargs = {} if max_wait_seconds is not None: wait_period_kwargs['max_wait_seconds'] = max_wait_seconds if wait_interval_seconds is not None: wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + if 'opc-work-request-id' not in result.headers: + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state') + cli_util.render_response(result, ctx) + return - click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) - result = oci.wait_until(client, client.get_stream(result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + click.echo('Action completed. Waiting until the work request has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_work_request(result.headers['opc-work-request-id']), 'status', wait_for_state, **wait_period_kwargs) except oci.exceptions.MaximumWaitTimeExceeded as e: # If we fail, we should show an error, but we should still provide the information to the customer - click.echo('Failed to wait until the resource entered the specified state. Outputting last known resource state', file=sys.stderr) + click.echo('Failed to wait until the work request entered the specified state. Outputting last known resource state', file=sys.stderr) cli_util.render_response(result, ctx) sys.exit(2) except Exception: - click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state', file=sys.stderr) cli_util.render_response(result, ctx) raise else: - click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + click.echo('Unable to wait for the work request to enter the specified state', file=sys.stderr) cli_util.render_response(result, ctx) @stream_pool_group.command(name=cli_util.override('stream_admin.update_stream_pool.command_name', 'update'), help=u"""Updates the specified stream pool. \n[Command Reference](updateStreamPool)""") @cli_util.option('--stream-pool-id', required=True, help=u"""The OCID of the stream pool.""") -@cli_util.option('--name', help=u"""""") +@cli_util.option('--name', help=u"""The name of the stream pool. Avoid entering confidential information. + +Example: `MyStreamPool`""") @cli_util.option('--kafka-settings', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) @cli_util.option('--custom-encryption-key-details', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) @cli_util.option('--freeform-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Free-form tags for this resource. Each tag is a simple key-value pair that is applied with no predefined name, type, or namespace. Exists for cross-compatibility only. For more information, see [Resource Tags]. @@ -977,9 +1288,9 @@ def update_stream(ctx, from_json, force, wait_for_state, max_wait_seconds, wait_ Example: `{\"Operations\": {\"CostCenter\": \"42\"}}`""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) @cli_util.option('--if-match', help=u"""For optimistic concurrency control. In the PUT or DELETE call for a resource, set the if-match parameter to the value of the etag from a previous GET or POST response for that resource. The resource will be updated or deleted only if the etag you provide matches the resource's current etag value.""") @cli_util.option('--force', help="""Perform update without prompting for confirmation.""", is_flag=True) -@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED", "UPDATING"]), multiple=True, help="""This operation creates, modifies or deletes a resource that has a defined lifecycle state. Specify this option to perform the action and then wait until the resource reaches a given lifecycle state. Multiple states can be specified, returning on the first state. For example, --wait-for-state CREATING --wait-for-state UPDATING would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") -@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") -@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the resource has reached the lifecycle state defined by --wait-for-state. Defaults to 30 seconds.""") +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "WAITING", "NEEDS_ATTENTION", "FAILED", "SUCCEEDED", "CANCELING", "CANCELED"]), multiple=True, help="""This operation asynchronously creates, modifies or deletes a resource and uses a work request to track the progress of the operation. Specify this option to perform the action and then wait until the work request reaches a certain state. Multiple states can be specified, returning on the first state. For example, --wait-for-state ACCEPTED --wait-for-state CANCELED would return on whichever lifecycle state is reached first. If timeout is reached, a return code of 2 is returned. For any other error, a return code of 1 is returned.""") +@cli_util.option('--max-wait-seconds', type=click.INT, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") +@cli_util.option('--wait-interval-seconds', type=click.INT, help="""Check every --wait-interval-seconds to see whether the work request has reached the state defined by --wait-for-state. Defaults to 30 seconds.""") @json_skeleton_utils.get_cli_json_input_option({'kafka-settings': {'module': 'streaming', 'class': 'KafkaSettings'}, 'custom-encryption-key-details': {'module': 'streaming', 'class': 'CustomEncryptionKeyDetails'}, 'freeform-tags': {'module': 'streaming', 'class': 'dict(str, string)'}, 'security-attributes': {'module': 'streaming', 'class': 'dict(str, dict(str, object))'}, 'defined-tags': {'module': 'streaming', 'class': 'dict(str, dict(str, object))'}}) @cli_util.help_option @click.pass_context @@ -1027,25 +1338,29 @@ def update_stream_pool(ctx, from_json, force, wait_for_state, max_wait_seconds, ) if wait_for_state: - if hasattr(client, 'get_stream_pool') and callable(getattr(client, 'get_stream_pool')): + if hasattr(client, 'get_work_request') and callable(getattr(client, 'get_work_request')): try: wait_period_kwargs = {} if max_wait_seconds is not None: wait_period_kwargs['max_wait_seconds'] = max_wait_seconds if wait_interval_seconds is not None: wait_period_kwargs['max_interval_seconds'] = wait_interval_seconds + if 'opc-work-request-id' not in result.headers: + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state') + cli_util.render_response(result, ctx) + return - click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) - result = oci.wait_until(client, client.get_stream_pool(result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + click.echo('Action completed. Waiting until the work request has entered state: {}'.format(wait_for_state), file=sys.stderr) + result = oci.wait_until(client, client.get_work_request(result.headers['opc-work-request-id']), 'status', wait_for_state, **wait_period_kwargs) except oci.exceptions.MaximumWaitTimeExceeded as e: # If we fail, we should show an error, but we should still provide the information to the customer - click.echo('Failed to wait until the resource entered the specified state. Outputting last known resource state', file=sys.stderr) + click.echo('Failed to wait until the work request entered the specified state. Outputting last known resource state', file=sys.stderr) cli_util.render_response(result, ctx) sys.exit(2) except Exception: - click.echo('Encountered error while waiting for resource to enter the specified state. Outputting last known resource state', file=sys.stderr) + click.echo('Encountered error while waiting for work request to enter the specified state. Outputting last known resource state', file=sys.stderr) cli_util.render_response(result, ctx) raise else: - click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + click.echo('Unable to wait for the work request to enter the specified state', file=sys.stderr) cli_util.render_response(result, ctx) diff --git a/services/streaming/tests/util/generated/command_to_api.py b/services/streaming/tests/util/generated/command_to_api.py index 2bbd17f18..8cf804a8f 100644 --- a/services/streaming/tests/util/generated/command_to_api.py +++ b/services/streaming/tests/util/generated/command_to_api.py @@ -14,9 +14,13 @@ "stream_admin.get_connect_harness": "oci.streaming.StreamAdminClient.get_connect_harness", "stream_admin.get_stream": "oci.streaming.StreamAdminClient.get_stream", "stream_admin.get_stream_pool": "oci.streaming.StreamAdminClient.get_stream_pool", + "stream_admin.get_work_request": "oci.streaming.StreamAdminClient.get_work_request", "stream_admin.list_connect_harnesses": "oci.streaming.StreamAdminClient.list_connect_harnesses", "stream_admin.list_stream_pools": "oci.streaming.StreamAdminClient.list_stream_pools", "stream_admin.list_streams": "oci.streaming.StreamAdminClient.list_streams", + "stream_admin.list_work_request_errors": "oci.streaming.StreamAdminClient.list_work_request_errors", + "stream_admin.list_work_request_logs": "oci.streaming.StreamAdminClient.list_work_request_logs", + "stream_admin.list_work_requests": "oci.streaming.StreamAdminClient.list_work_requests", "stream_admin.update_connect_harness": "oci.streaming.StreamAdminClient.update_connect_harness", "stream_admin.update_stream": "oci.streaming.StreamAdminClient.update_stream", "stream_admin.update_stream_pool": "oci.streaming.StreamAdminClient.update_stream_pool", diff --git a/setup.py b/setup.py index ceca9804e..d274b2149 100644 --- a/setup.py +++ b/setup.py @@ -30,7 +30,7 @@ def open_relative(*path): readme = f.read() requires = [ - 'oci==2.174.0', + 'oci==2.175.0', 'arrow>=1.0.0,<2.0.0', 'certifi>=2025.1.31,<2026.0.0', 'click<=8.1.2', diff --git a/src/oci_cli/cli_util.py b/src/oci_cli/cli_util.py index 046d99518..689dd1c0a 100644 --- a/src/oci_cli/cli_util.py +++ b/src/oci_cli/cli_util.py @@ -452,7 +452,7 @@ def create_config_and_signer_based_on_click_context(ctx): try: config.validate_config(client_config, **kwargs) except exceptions.InvalidConfig as bad_config: - if type(bad_config.errors) != str: + if type(bad_config.errors) is not str: table = render_config_errors(bad_config) else: table = bad_config.errors diff --git a/src/oci_cli/custom_types/cli_case_insensitive_choice.py b/src/oci_cli/custom_types/cli_case_insensitive_choice.py index 8cf506555..1516b3ed2 100644 --- a/src/oci_cli/custom_types/cli_case_insensitive_choice.py +++ b/src/oci_cli/custom_types/cli_case_insensitive_choice.py @@ -12,7 +12,7 @@ def __init__(self, choices): # This is: https://github.com/pallets/click/blob/b471d346e93b818d7c8a87d8cee9e0705435ac19/click/types.py#L145 but instead of relying # on the presence of a token_normalize_func, we always do a case insensitive match def convert(self, value, param, ctx): - if type(value) == list: + if type(value) is list: if set(map(str.lower, value)).issubset(set(map(str.lower, self.choices))): return value else: diff --git a/src/oci_cli/service_mapping.py b/src/oci_cli/service_mapping.py index b4f8d9baa..63ac9e7a3 100644 --- a/src/oci_cli/service_mapping.py +++ b/src/oci_cli/service_mapping.py @@ -188,6 +188,11 @@ "Container Registry", "Others" ], + "costad": [ + "costad", + "CostAd", + "Others" + ], "cpg": [ "cluster_placement_groups", "Cluster Placement Groups", @@ -265,7 +270,7 @@ ], "dbtools-runtime": [ "database_tools_runtime", - "Database Tools Service Runtime", + "Database Tools Runtime", "Others" ], "delegate-access-control": [ diff --git a/src/oci_cli/version.py b/src/oci_cli/version.py index 99cf30a63..e716be966 100644 --- a/src/oci_cli/version.py +++ b/src/oci_cli/version.py @@ -2,4 +2,4 @@ # Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. # This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. -__version__ = '3.82.0' +__version__ = '3.83.0' diff --git a/tests/test_json_skeleton_command_coverage.py b/tests/test_json_skeleton_command_coverage.py index 8c898f5ec..5a33bae8a 100644 --- a/tests/test_json_skeleton_command_coverage.py +++ b/tests/test_json_skeleton_command_coverage.py @@ -146,7 +146,7 @@ def append_failed_commands_to_file(failed_commands): def process_json_input(input, tmpdir): modified_input = json.loads(input) # if the command accepts list of objects, we will process the first element in the list and pass it to the test. - if type(input) == list: + if type(input) is list: modified_input = modified_input[0] # Remove waiter and listing options modified_input.pop('waitForState', None)