From 7a09d2cee75af7a996edda4688eaf37a7344721a Mon Sep 17 00:00:00 2001 From: harshkumar-dev Date: Mon, 30 Aug 2021 20:09:34 +0000 Subject: [PATCH] Releasing version 3.0.3 Co-authored-by: Kern Lee Co-authored-by: Hamada Ibrahim Co-authored-by: Vishwas Bhat --- CHANGELOG.rst | 26 ++ THIRD_PARTY_LICENSES.txt | 211 ++++++++- requirements.txt | 5 +- .../generated/datacatalog_cli.py | 19 +- .../src/oci_cli_event/__init__.py | 3 + .../src/oci_cli_event/event_cli_extended.py | 34 ++ .../src/oci_cli_event/generated/__init__.py | 3 + .../generated/client_mappings.py | 13 + .../src/oci_cli_event/generated/event_cli.py | 429 ++++++++++++++++++ .../generated/os_management_service_cli.py | 14 + .../generated/osmanagement_cli.py | 131 +++++- setup.py | 7 +- src/oci_cli/cli_util.py | 34 +- src/oci_cli/version.py | 2 +- tests/test_config_validation.py | 55 +++ tests/test_root_options.py | 8 +- 16 files changed, 939 insertions(+), 55 deletions(-) create mode 100644 services/os_management/src/oci_cli_event/__init__.py create mode 100644 services/os_management/src/oci_cli_event/event_cli_extended.py create mode 100644 services/os_management/src/oci_cli_event/generated/__init__.py create mode 100644 services/os_management/src/oci_cli_event/generated/client_mappings.py create mode 100644 services/os_management/src/oci_cli_event/generated/event_cli.py create mode 100644 services/os_management/src/oci_cli_os_management/generated/os_management_service_cli.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 813e355aa..b3dfb7b6c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,32 @@ All notable changes to this project will be documented in this file. The format is based on `Keep a Changelog `__. +3.0.3 - 2021-08-31 +------------------- +Added +~~~~~ +* Prompt to create a config file with a profile using API key pair authentication if a CLI command is run with a nonexistent config file and api_key auth + +* Support for Oracle Analytics Cloud and OCI Vault integration on connections in Data Catalog service + + * ``oci data-catalog data-asset parse-connection --wallet-secret-id, --wallet-secret-name`` + +* Support for critical event monitoring in the OS Management service + + * ``oci os-management event`` + * ``oci os-management managed-instance install-all-updates --update-type`` + * ``oci os-management managed-instance install-all-windows-updates --update-type`` + * ``oci os-management managed-instance-group install-all-updates`` + * ``oci os-management scheduled-job list --is-restricted`` + * ``oci os-management update-managed-instance-details update-managed-instance`` + * ``oci os-management work-request-summary`` + +Changed +~~~~~~~ +* Modified supported version for the following package: arrow (>=1.0.0), cryptography (>=3.2.1, <=3.4.7) + +* Configparser has been removed from the requirements + 3.0.2 - 2021-08-24 ------------------- Added diff --git a/THIRD_PARTY_LICENSES.txt b/THIRD_PARTY_LICENSES.txt index a4ccbbf2b..e613eeb9a 100644 --- a/THIRD_PARTY_LICENSES.txt +++ b/THIRD_PARTY_LICENSES.txt @@ -1,6 +1,194 @@ arrow ============= -Copyright 2019 Chris Smith + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2021 Chris Smith Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -48,30 +236,19 @@ Redistribution and use in source and binary forms, with or without modification, THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -configparser -============= -Author: Ɓukasz Langa and contributors. -This is the MIT license: http://www.opensource.org/licenses/mit-license.php. - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - cryptography ============= -LICENSE: https://github.com/pyca/cryptography/blob/3.3.x/LICENSE +LICENSE: https://github.com/pyca/cryptography/blob/3.2.x/LICENSE This software is made available under the terms of *either* of the licenses found in LICENSE.APACHE or LICENSE.BSD. Contributions to cryptography are made under the terms of *both* these licenses. -The code used in the OS random engine is derived from CPython, and is licensed -under the terms of the PSF License Agreement. +The code used in the OpenSSL locking callback and OS random engine is derived +from CPython, and is licensed under the terms of the PSF License Agreement. ___________________________________________________________________________ -LICENSE.APACHE: https://github.com/pyca/cryptography/blob/3.3.x/LICENSE.APACHE +LICENSE.APACHE: https://github.com/pyca/cryptography/blob/3.2.x/LICENSE.APACHE Apache License @@ -278,7 +455,7 @@ LICENSE.APACHE: https://github.com/pyca/cryptography/blob/3.3.x/LICENSE.APACHE ___________________________________________________________________________ -LICENSE.BSD: https://github.com/pyca/cryptography/blob/3.3.x/LICENSE.BSD +LICENSE.BSD: https://github.com/pyca/cryptography/blob/3.2.x/LICENSE.BSD Copyright (c) Individual contributors. All rights reserved. diff --git a/requirements.txt b/requirements.txt index fdb28d579..3f5f08a6a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,11 +3,10 @@ # you may need to use the --extra-index-url option instead. appdirs==1.4.3 -arrow==0.17.0 +arrow>=1.0.0 certifi cffi>=1.9.1 click==7.1.2 -configparser==4.0.2 coverage==4.5.2 cryptography==3.3.2 httpsig-cffi==15.0.0 @@ -15,7 +14,7 @@ Jinja2==2.11.3 jmespath==0.10.0 ndg-httpsclient==0.4.2 mock==2.0.0 -oci==2.44.1 +oci==2.44.2 packaging==20.2 pluggy==0.13.0 py==1.10.0 diff --git a/services/data_catalog/src/oci_cli_data_catalog/generated/datacatalog_cli.py b/services/data_catalog/src/oci_cli_data_catalog/generated/datacatalog_cli.py index e88ef4df2..1df7d744d 100644 --- a/services/data_catalog/src/oci_cli_data_catalog/generated/datacatalog_cli.py +++ b/services/data_catalog/src/oci_cli_data_catalog/generated/datacatalog_cli.py @@ -15,7 +15,8 @@ from oci_cli.aliasing import CommandGroupWithAlias -@cli.command(cli_util.override('data_catalog.data_catalog_root_group.command_name', 'data-catalog'), cls=CommandGroupWithAlias, help=cli_util.override('data_catalog.data_catalog_root_group.help', """Use the Data Catalog APIs to collect, organize, find, access, understand, enrich, and activate technical, business, and operational metadata."""), short_help=cli_util.override('data_catalog.data_catalog_root_group.short_help', """Data Catalog API""")) +@cli.command(cli_util.override('data_catalog.data_catalog_root_group.command_name', 'data-catalog'), cls=CommandGroupWithAlias, help=cli_util.override('data_catalog.data_catalog_root_group.help', """Use the Data Catalog APIs to collect, organize, find, access, understand, enrich, and activate technical, business, and operational metadata. +For more information, see [Data Catalog]."""), short_help=cli_util.override('data_catalog.data_catalog_root_group.short_help', """Data Catalog API""")) @cli_util.help_option_group def data_catalog_root_group(): pass @@ -4483,8 +4484,8 @@ def list_attribute_tags(ctx, from_json, all_pages, page_size, catalog_id, data_a @cli_util.option('--position', type=click.INT, help=u"""Position of the attribute in the record definition.""") @cli_util.option('--precision', type=click.INT, help=u"""Precision of the attribute value usually applies to float data type.""") @cli_util.option('--scale', type=click.INT, help=u"""Scale of the attribute value usually applies to float data type.""") -@cli_util.option('--fields', type=custom_types.CliCaseInsensitiveChoice(["key", "displayName", "description", "entityKey", "lifecycleState", "timeCreated", "externalDataType", "externalKey", "length", "precision", "scale", "isNullable", "uri", "path", "minCollectionCount", "maxCollectionCount", "datatypeEntityKey", "externalDatatypeEntityKey", "parentAttributeKey", "externalParentAttributeKey"]), multiple=True, help=u"""Specifies the fields to return in an entity attribute summary response.""") -@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('--fields', type=custom_types.CliCaseInsensitiveChoice(["key", "displayName", "description", "entityKey", "lifecycleState", "timeCreated", "externalDataType", "externalKey", "length", "precision", "scale", "isNullable", "uri", "path", "minCollectionCount", "maxCollectionCount", "datatypeEntityKey", "externalDatatypeEntityKey", "parentAttributeKey", "externalParentAttributeKey", "position"]), multiple=True, help=u"""Specifies the fields to return in an entity attribute summary response.""") +@cli_util.option('--sort-by', type=custom_types.CliCaseInsensitiveChoice(["TIMECREATED", "DISPLAYNAME", "POSITION"]), 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. Default order for POSITION is ascending. If no value is specified POSITION 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('--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.""") @@ -4812,7 +4813,7 @@ def list_connections(ctx, from_json, all_pages, page_size, catalog_id, data_asse @cli_util.option('--display-name', help=u"""A filter to return only resources that match the entire display name given. The match is not case sensitive.""") @cli_util.option('--display-name-contains', help=u"""A filter to return only resources that match display name pattern given. The match is not case sensitive. For Example : /folders?displayNameContains=Cu.* The above would match all folders with display name that starts with \"Cu\".""") @cli_util.option('--data-types', type=custom_types.CliCaseInsensitiveChoice(["TEXT", "RICH_TEXT", "BOOLEAN", "NUMBER", "DATE"]), multiple=True, help=u"""Return the custom properties which has specified data types""") -@cli_util.option('--type-name', type=custom_types.CliCaseInsensitiveChoice(["DATA_ASSET", "AUTONOMOUS_DATA_WAREHOUSE", "HIVE", "KAFKA", "MYSQL", "ORACLE_OBJECT_STORAGE", "AUTONOMOUS_TRANSACTION_PROCESSING", "ORACLE", "POSTGRESQL", "MICROSOFT_AZURE_SQL_DATABASE", "MICROSOFT_SQL_SERVER", "IBM_DB2", "DATA_ENTITY", "LOGICAL_ENTITY", "TABLE", "VIEW", "ATTRIBUTE", "FOLDER", "ORACLE_ANALYTICS_SERVER", "ORACLE_ANALYTICS_CLOUD", "ORACLE_ANALYTICS_SUBJECT_AREA", "ORACLE_ANALYTICS_DASHBOARD", "ORACLE_ANALYTICS_BUSINESS_MODEL", "ORACLE_ANALYTICS_PHYSICAL_DATABASE", "ORACLE_ANALYTICS_PHYSICAL_SCHEMA", "ORACLE_ANALYTICS_PRESENTATION_TABLE", "ORACLE_ANALYTICS_LOGICAL_TABLE", "ORACLE_ANALYTICS_PHYSICAL_TABLE", "ORACLE_ANALYTICS_ANALYSIS", "DATABASE_SCHEMA", "TOPIC", "CONNECTION", "GLOSSARY", "TERM", "CATEGORY", "FILE", "BUCKET", "MESSAGE", "UNRECOGNIZED_FILE"]), multiple=True, help=u"""A filter to return only resources that match the entire type name given. The match is not case sensitive""") +@cli_util.option('--type-name', type=custom_types.CliCaseInsensitiveChoice(["DATA_ASSET", "AUTONOMOUS_DATA_WAREHOUSE", "HIVE", "KAFKA", "MYSQL", "ORACLE_OBJECT_STORAGE", "AUTONOMOUS_TRANSACTION_PROCESSING", "ORACLE", "POSTGRESQL", "MICROSOFT_AZURE_SQL_DATABASE", "MICROSOFT_SQL_SERVER", "IBM_DB2", "DATA_ENTITY", "LOGICAL_ENTITY", "TABLE", "VIEW", "ATTRIBUTE", "FOLDER", "ORACLE_ANALYTICS_SUBJECT_AREA_COLUMN", "ORACLE_ANALYTICS_LOGICAL_COLUMN", "ORACLE_ANALYTICS_PHYSICAL_COLUMN", "ORACLE_ANALYTICS_ANALYSIS_COLUMN", "ORACLE_ANALYTICS_SERVER", "ORACLE_ANALYTICS_CLOUD", "ORACLE_ANALYTICS_SUBJECT_AREA", "ORACLE_ANALYTICS_DASHBOARD", "ORACLE_ANALYTICS_BUSINESS_MODEL", "ORACLE_ANALYTICS_PHYSICAL_DATABASE", "ORACLE_ANALYTICS_PHYSICAL_SCHEMA", "ORACLE_ANALYTICS_PRESENTATION_TABLE", "ORACLE_ANALYTICS_LOGICAL_TABLE", "ORACLE_ANALYTICS_PHYSICAL_TABLE", "ORACLE_ANALYTICS_ANALYSIS", "DATABASE_SCHEMA", "TOPIC", "CONNECTION", "GLOSSARY", "TERM", "CATEGORY", "FILE", "BUCKET", "MESSAGE", "UNRECOGNIZED_FILE"]), multiple=True, help=u"""A filter to return only resources that match the entire type name given. The match is not case sensitive""") @cli_util.option('--lifecycle-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "INACTIVE", "UPDATING", "DELETING", "DELETED", "FAILED", "MOVING"]), help=u"""A filter to return only resources that match the specified lifecycle state. The value is case insensitive.""") @cli_util.option('--time-created', type=custom_types.CLI_DATETIME, help=u"""Time that the resource was created. An [RFC3339] formatted datetime string.""" + custom_types.CLI_DATETIME.VALID_DATETIME_CLI_HELP_MESSAGE) @cli_util.option('--time-updated', type=custom_types.CLI_DATETIME, help=u"""Time that the resource was updated. An [RFC3339] formatted datetime string.""" + custom_types.CLI_DATETIME.VALID_DATETIME_CLI_HELP_MESSAGE) @@ -7018,13 +7019,15 @@ def object_stats(ctx, from_json, catalog_id, sort_by, sort_order, limit, page): @cli_util.option('--data-asset-key', required=True, help=u"""Unique data asset key.""") @cli_util.option('--connection-detail', type=custom_types.CLI_COMPLEX_TYPE, help=u"""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) @cli_util.option('--connection-payload', help=u"""The information used to parse the connection from the wallet file payload.""") +@cli_util.option('--wallet-secret-id', help=u"""OCID of the OCI Vault secret holding the Oracle wallet to parse.""") +@cli_util.option('--wallet-secret-name', help=u"""Name of the OCI Vault secret holding the Oracle wallet to parse.""") @cli_util.option('--connection-key', help=u"""Unique connection key.""") @json_skeleton_utils.get_cli_json_input_option({'connection-detail': {'module': 'data_catalog', 'class': 'Connection'}}) @cli_util.help_option @click.pass_context @json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'connection-detail': {'module': 'data_catalog', 'class': 'Connection'}}, output_type={'module': 'data_catalog', 'class': 'list[ConnectionAliasSummary]'}) @cli_util.wrap_exceptions -def parse_connection(ctx, from_json, catalog_id, data_asset_key, connection_detail, connection_payload, connection_key): +def parse_connection(ctx, from_json, catalog_id, data_asset_key, connection_detail, connection_payload, wallet_secret_id, wallet_secret_name, connection_key): if isinstance(catalog_id, six.string_types) and len(catalog_id.strip()) == 0: raise click.UsageError('Parameter --catalog-id cannot be whitespace or empty string') @@ -7045,6 +7048,12 @@ def parse_connection(ctx, from_json, catalog_id, data_asset_key, connection_deta if connection_payload is not None: _details['connectionPayload'] = connection_payload + if wallet_secret_id is not None: + _details['walletSecretId'] = wallet_secret_id + + if wallet_secret_name is not None: + _details['walletSecretName'] = wallet_secret_name + client = cli_util.build_client('data_catalog', 'data_catalog', ctx) result = client.parse_connection( catalog_id=catalog_id, diff --git a/services/os_management/src/oci_cli_event/__init__.py b/services/os_management/src/oci_cli_event/__init__.py new file mode 100644 index 000000000..69bf98ddb --- /dev/null +++ b/services/os_management/src/oci_cli_event/__init__.py @@ -0,0 +1,3 @@ +# coding: utf-8 +# Copyright (c) 2016, 2021, 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. diff --git a/services/os_management/src/oci_cli_event/event_cli_extended.py b/services/os_management/src/oci_cli_event/event_cli_extended.py new file mode 100644 index 000000000..5e4690048 --- /dev/null +++ b/services/os_management/src/oci_cli_event/event_cli_extended.py @@ -0,0 +1,34 @@ +# coding: utf-8 +# Copyright (c) 2016, 2021, 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. + +from services.os_management.src.oci_cli_event.generated import event_cli +from oci_cli import cli_util + +# Event - move and rename commands +event_root_group = event_cli.event_root_group + +event_root_group.commands.pop(event_cli.binary_group.name) +event_root_group.add_command(event_cli.get_event_content) +cli_util.rename_command(event_cli, event_root_group, event_cli.get_event_content, "get-content") + +event_root_group.commands.pop(event_cli.event_group.name) +event_root_group.add_command(event_cli.get_event) +event_root_group.add_command(event_cli.update_event) + +event_root_group.commands.pop(event_cli.event_collection_group.name) +event_root_group.add_command(event_cli.list_events) +cli_util.rename_command(event_cli, event_root_group, event_cli.list_events, "list") + +event_root_group.commands.pop(event_cli.event_content_group.name) +event_root_group.add_command(event_cli.delete_event_content) +cli_util.rename_command(event_cli, event_root_group, event_cli.delete_event_content, "delete-content") +event_root_group.add_command(event_cli.upload_event_content) +cli_util.rename_command(event_cli, event_root_group, event_cli.upload_event_content, "upload-content") + +event_root_group.commands.pop(event_cli.event_report_group.name) +event_root_group.add_command(event_cli.get_event_report) +cli_util.rename_command(event_cli, event_root_group, event_cli.get_event_report, "get-report") + +event_root_group.commands.pop(event_cli.related_event_collection_group.name) +event_root_group.add_command(event_cli.list_related_events) diff --git a/services/os_management/src/oci_cli_event/generated/__init__.py b/services/os_management/src/oci_cli_event/generated/__init__.py new file mode 100644 index 000000000..69bf98ddb --- /dev/null +++ b/services/os_management/src/oci_cli_event/generated/__init__.py @@ -0,0 +1,3 @@ +# coding: utf-8 +# Copyright (c) 2016, 2021, 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. diff --git a/services/os_management/src/oci_cli_event/generated/client_mappings.py b/services/os_management/src/oci_cli_event/generated/client_mappings.py new file mode 100644 index 000000000..dead7ce44 --- /dev/null +++ b/services/os_management/src/oci_cli_event/generated/client_mappings.py @@ -0,0 +1,13 @@ +# coding: utf-8 +# Copyright (c) 2016, 2021, 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. + +import oci +from oci_cli.cli_clients import CLIENT_MAP +from oci_cli.cli_clients import MODULE_TO_TYPE_MAPPINGS +from oci.os_management import EventClient + +MODULE_TO_TYPE_MAPPINGS["os_management"] = oci.os_management.models.os_management_type_mapping +if CLIENT_MAP.get("os_management") is None: + CLIENT_MAP["os_management"] = {} +CLIENT_MAP["os_management"]["event"] = EventClient diff --git a/services/os_management/src/oci_cli_event/generated/event_cli.py b/services/os_management/src/oci_cli_event/generated/event_cli.py new file mode 100644 index 000000000..14c871ae0 --- /dev/null +++ b/services/os_management/src/oci_cli_event/generated/event_cli.py @@ -0,0 +1,429 @@ +# coding: utf-8 +# Copyright (c) 2016, 2021, 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. + +from __future__ import print_function +import click +import oci # noqa: F401 +import six # noqa: F401 +import sys # noqa: F401 +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 +from services.os_management.src.oci_cli_os_management.generated import os_management_service_cli + + +@click.command(cli_util.override('event.event_root_group.command_name', 'event'), cls=CommandGroupWithAlias, help=cli_util.override('event.event_root_group.help', """API for the OS Management service. Use these API operations for working +with Managed instances and Managed instance groups."""), short_help=cli_util.override('event.event_root_group.short_help', """OS Management API""")) +@cli_util.help_option_group +def event_root_group(): + pass + + +@click.command(cli_util.override('event.related_event_collection_group.command_name', 'related-event-collection'), cls=CommandGroupWithAlias, help="""Results of a event occurence search. Contains RelatedEventSummary.""") +@cli_util.help_option_group +def related_event_collection_group(): + pass + + +@click.command(cli_util.override('event.event_content_group.command_name', 'event-content'), cls=CommandGroupWithAlias, help="""Information about the data collected as a ZIP file when the event occurred.""") +@cli_util.help_option_group +def event_content_group(): + pass + + +@click.command(cli_util.override('event.event_collection_group.command_name', 'event-collection'), cls=CommandGroupWithAlias, help="""Results of a event search. Contains both EventSummary items and other information, such as metadata.""") +@cli_util.help_option_group +def event_collection_group(): + pass + + +@click.command(cli_util.override('event.event_group.command_name', 'event'), cls=CommandGroupWithAlias, help="""Description of Event.""") +@cli_util.help_option_group +def event_group(): + pass + + +@click.command(cli_util.override('event.event_report_group.command_name', 'event-report'), cls=CommandGroupWithAlias, help="""Summary about event occurrences on a system.""") +@cli_util.help_option_group +def event_report_group(): + pass + + +@click.command(cli_util.override('event.binary_group.command_name', 'binary'), cls=CommandGroupWithAlias, help="""""") +@cli_util.help_option_group +def binary_group(): + pass + + +os_management_service_cli.os_management_service_group.add_command(event_root_group) +event_root_group.add_command(related_event_collection_group) +event_root_group.add_command(event_content_group) +event_root_group.add_command(event_collection_group) +event_root_group.add_command(event_group) +event_root_group.add_command(event_report_group) +event_root_group.add_command(binary_group) + + +@event_content_group.command(name=cli_util.override('event.delete_event_content.command_name', 'delete'), help=u"""Delete an event content ZIP archive from the service \n[Command Reference](deleteEventContent)""") +@cli_util.option('--managed-instance-id', required=True, help=u"""Instance Oracle Cloud identifier (ocid)""") +@cli_util.option('--event-id', required=True, help=u"""Unique Event identifier (OCID)""") +@cli_util.option('--compartment-id', required=True, help=u"""The ID of the compartment in which to list resources.""") +@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 +@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_event_content(ctx, from_json, managed_instance_id, event_id, compartment_id, if_match): + + if isinstance(managed_instance_id, six.string_types) and len(managed_instance_id.strip()) == 0: + raise click.UsageError('Parameter --managed-instance-id cannot be whitespace or empty string') + + if isinstance(event_id, six.string_types) and len(event_id.strip()) == 0: + raise click.UsageError('Parameter --event-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('os_management', 'event', ctx) + result = client.delete_event_content( + managed_instance_id=managed_instance_id, + event_id=event_id, + compartment_id=compartment_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@event_group.command(name=cli_util.override('event.get_event.command_name', 'get'), help=u"""Gets an Event by identifier \n[Command Reference](getEvent)""") +@cli_util.option('--managed-instance-id', required=True, help=u"""Instance Oracle Cloud identifier (ocid)""") +@cli_util.option('--event-id', required=True, help=u"""Unique Event identifier (OCID)""") +@cli_util.option('--compartment-id', required=True, help=u"""The ID of the compartment in which to list resources.""") +@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': 'os_management', 'class': 'Event'}) +@cli_util.wrap_exceptions +def get_event(ctx, from_json, managed_instance_id, event_id, compartment_id): + + if isinstance(managed_instance_id, six.string_types) and len(managed_instance_id.strip()) == 0: + raise click.UsageError('Parameter --managed-instance-id cannot be whitespace or empty string') + + if isinstance(event_id, six.string_types) and len(event_id.strip()) == 0: + raise click.UsageError('Parameter --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('os_management', 'event', ctx) + result = client.get_event( + managed_instance_id=managed_instance_id, + event_id=event_id, + compartment_id=compartment_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@binary_group.command(name=cli_util.override('event.get_event_content.command_name', 'get-event-content'), help=u"""Get additional data about a event as a ZIP archive. The archive content depends on the event eventType. \n[Command Reference](getEventContent)""") +@cli_util.option('--managed-instance-id', required=True, help=u"""Instance Oracle Cloud identifier (ocid)""") +@cli_util.option('--event-id', required=True, help=u"""Unique Event identifier (OCID)""") +@cli_util.option('--compartment-id', required=True, help=u"""The ID of the compartment in which to list resources.""") +@cli_util.option('--file', type=click.File(mode='wb'), required=True, help="The name of the file that will receive the response data, or '-' to write to STDOUT.") +@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 get_event_content(ctx, from_json, file, managed_instance_id, event_id, compartment_id): + + if isinstance(managed_instance_id, six.string_types) and len(managed_instance_id.strip()) == 0: + raise click.UsageError('Parameter --managed-instance-id cannot be whitespace or empty string') + + if isinstance(event_id, six.string_types) and len(event_id.strip()) == 0: + raise click.UsageError('Parameter --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('os_management', 'event', ctx) + result = client.get_event_content( + managed_instance_id=managed_instance_id, + event_id=event_id, + compartment_id=compartment_id, + **kwargs + ) + + # If outputting to stdout we don't want to print a progress bar because it will get mixed up with the output + # Also we need a non-zero Content-Length in order to display a meaningful progress bar + bar = None + if hasattr(file, 'name') and file.name != '' and 'Content-Length' in result.headers: + content_length = int(result.headers['Content-Length']) + if content_length > 0: + bar = click.progressbar(length=content_length, label='Downloading file') + + try: + if bar: + bar.__enter__() + + # TODO: Make the download size a configurable option + # use decode_content=True to automatically unzip service responses (this should be overridden for object storage) + for chunk in result.data.raw.stream(cli_constants.MEBIBYTE, decode_content=True): + if bar: + bar.update(len(chunk)) + file.write(chunk) + finally: + if bar: + bar.render_finish() + file.close() + + +@event_report_group.command(name=cli_util.override('event.get_event_report.command_name', 'get'), help=u"""Get summary information about events on this instance. \n[Command Reference](getEventReport)""") +@cli_util.option('--managed-instance-id', required=True, help=u"""Instance Oracle Cloud identifier (ocid)""") +@cli_util.option('--compartment-id', required=True, help=u"""The ID of the compartment in which to list resources.""") +@cli_util.option('--latest-timestamp-less-than', type=custom_types.CLI_DATETIME, help=u"""filter event occurrence. Selecting only those last occurred before given date in ISO 8601 format Example: 2017-07-14T02:40:00.000Z""" + custom_types.CLI_DATETIME.VALID_DATETIME_CLI_HELP_MESSAGE) +@cli_util.option('--latest-timestamp-greater-than-or-equal-to', type=custom_types.CLI_DATETIME, help=u"""filter event occurrence. Selecting only those last occurred on or after given date in ISO 8601 format Example: 2017-07-14T02:40:00.000Z""" + custom_types.CLI_DATETIME.VALID_DATETIME_CLI_HELP_MESSAGE) +@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': 'os_management', 'class': 'EventReport'}) +@cli_util.wrap_exceptions +def get_event_report(ctx, from_json, managed_instance_id, compartment_id, latest_timestamp_less_than, latest_timestamp_greater_than_or_equal_to): + + if isinstance(managed_instance_id, six.string_types) and len(managed_instance_id.strip()) == 0: + raise click.UsageError('Parameter --managed-instance-id cannot be whitespace or empty string') + + kwargs = {} + if latest_timestamp_less_than is not None: + kwargs['latest_timestamp_less_than'] = latest_timestamp_less_than + if latest_timestamp_greater_than_or_equal_to is not None: + kwargs['latest_timestamp_greater_than_or_equal_to'] = latest_timestamp_greater_than_or_equal_to + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('os_management', 'event', ctx) + result = client.get_event_report( + managed_instance_id=managed_instance_id, + compartment_id=compartment_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@event_collection_group.command(name=cli_util.override('event.list_events.command_name', 'list-events'), help=u"""Returns a list of Events. \n[Command Reference](listEvents)""") +@cli_util.option('--managed-instance-id', required=True, help=u"""Instance Oracle Cloud identifier (ocid)""") +@cli_util.option('--compartment-id', required=True, help=u"""The ID of the compartment in which to list resources.""") +@cli_util.option('--event-id', help=u"""Unique event identifier (OCID)""") +@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", "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('--event-type', type=custom_types.CliCaseInsensitiveChoice(["KERNEL_OOPS", "KERNEL_CRASH", "CRASH", "EXPLOIT_ATTEMPT", "COMPLIANCE", "TUNING_SUGGESTION", "TUNING_APPLIED", "SECURITY", "ERROR", "WARNING"]), help=u"""A filter to return only event of given type.""") +@cli_util.option('--latest-timestamp-less-than', type=custom_types.CLI_DATETIME, help=u"""filter event occurrence. Selecting only those last occurred before given date in ISO 8601 format Example: 2017-07-14T02:40:00.000Z""" + custom_types.CLI_DATETIME.VALID_DATETIME_CLI_HELP_MESSAGE) +@cli_util.option('--latest-timestamp-greater-than-or-equal-to', type=custom_types.CLI_DATETIME, help=u"""filter event occurrence. Selecting only those last occurred on or after given date in ISO 8601 format Example: 2017-07-14T02:40:00.000Z""" + custom_types.CLI_DATETIME.VALID_DATETIME_CLI_HELP_MESSAGE) +@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': 'os_management', 'class': 'EventCollection'}) +@cli_util.wrap_exceptions +def list_events(ctx, from_json, all_pages, page_size, managed_instance_id, compartment_id, event_id, limit, page, sort_order, sort_by, event_type, latest_timestamp_less_than, latest_timestamp_greater_than_or_equal_to): + + if all_pages and limit: + raise click.UsageError('If you provide the --all option you cannot provide the --limit option') + + if isinstance(managed_instance_id, six.string_types) and len(managed_instance_id.strip()) == 0: + raise click.UsageError('Parameter --managed-instance-id cannot be whitespace or empty string') + + kwargs = {} + if event_id is not None: + kwargs['event_id'] = event_id + 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 event_type is not None: + kwargs['event_type'] = event_type + if latest_timestamp_less_than is not None: + kwargs['latest_timestamp_less_than'] = latest_timestamp_less_than + if latest_timestamp_greater_than_or_equal_to is not None: + kwargs['latest_timestamp_greater_than_or_equal_to'] = latest_timestamp_greater_than_or_equal_to + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('os_management', 'event', ctx) + if all_pages: + if page_size: + kwargs['limit'] = page_size + + result = cli_util.list_call_get_all_results( + client.list_events, + managed_instance_id=managed_instance_id, + compartment_id=compartment_id, + **kwargs + ) + elif limit is not None: + result = cli_util.list_call_get_up_to_limit( + client.list_events, + limit, + page_size, + managed_instance_id=managed_instance_id, + compartment_id=compartment_id, + **kwargs + ) + else: + result = client.list_events( + managed_instance_id=managed_instance_id, + compartment_id=compartment_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@related_event_collection_group.command(name=cli_util.override('event.list_related_events.command_name', 'list-related-events'), help=u"""Returns a list of related events. For now pagination is not implemented. \n[Command Reference](listRelatedEvents)""") +@cli_util.option('--event-fingerprint', required=True, help=u"""Event fingerprint identifier""") +@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(["instanceId", "id", "eventFingerprint"]), help=u"""The field to sort by. Only one sort order may be provided. Default order for id is descending.""") +@cli_util.option('--latest-timestamp-less-than', type=custom_types.CLI_DATETIME, help=u"""filter event occurrence. Selecting only those last occurred before given date in ISO 8601 format Example: 2017-07-14T02:40:00.000Z""" + custom_types.CLI_DATETIME.VALID_DATETIME_CLI_HELP_MESSAGE) +@cli_util.option('--latest-timestamp-greater-than-or-equal-to', type=custom_types.CLI_DATETIME, help=u"""filter event occurrence. Selecting only those last occurred on or after given date in ISO 8601 format Example: 2017-07-14T02:40:00.000Z""" + custom_types.CLI_DATETIME.VALID_DATETIME_CLI_HELP_MESSAGE) +@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': 'os_management', 'class': 'RelatedEventCollection'}) +@cli_util.wrap_exceptions +def list_related_events(ctx, from_json, all_pages, page_size, event_fingerprint, compartment_id, limit, page, sort_order, sort_by, latest_timestamp_less_than, latest_timestamp_greater_than_or_equal_to): + + 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 latest_timestamp_less_than is not None: + kwargs['latest_timestamp_less_than'] = latest_timestamp_less_than + if latest_timestamp_greater_than_or_equal_to is not None: + kwargs['latest_timestamp_greater_than_or_equal_to'] = latest_timestamp_greater_than_or_equal_to + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('os_management', 'event', ctx) + if all_pages: + if page_size: + kwargs['limit'] = page_size + + result = cli_util.list_call_get_all_results( + client.list_related_events, + event_fingerprint=event_fingerprint, + compartment_id=compartment_id, + **kwargs + ) + elif limit is not None: + result = cli_util.list_call_get_up_to_limit( + client.list_related_events, + limit, + page_size, + event_fingerprint=event_fingerprint, + compartment_id=compartment_id, + **kwargs + ) + else: + result = client.list_related_events( + event_fingerprint=event_fingerprint, + compartment_id=compartment_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@event_group.command(name=cli_util.override('event.update_event.command_name', 'update'), help=u"""Updates an existing event associated to a managed instance \n[Command Reference](updateEvent)""") +@cli_util.option('--managed-instance-id', required=True, help=u"""Instance Oracle Cloud identifier (ocid)""") +@cli_util.option('--event-id', required=True, help=u"""Unique Event identifier (OCID)""") +@cli_util.option('--compartment-id', required=True, help=u"""The ID of the compartment in which to list resources.""") +@cli_util.option('--freeform-tags', type=custom_types.CLI_COMPLEX_TYPE, help=u"""Simple key-value pair that is 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"""Defined tags for this resource. Each key is predefined and scoped to a namespace. Example: `{\"foo-namespace\": {\"bar-key\": \"value\"}}`""" + 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) +@json_skeleton_utils.get_cli_json_input_option({'freeform-tags': {'module': 'os_management', 'class': 'dict(str, string)'}, 'defined-tags': {'module': 'os_management', 'class': 'dict(str, dict(str, object))'}}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'freeform-tags': {'module': 'os_management', 'class': 'dict(str, string)'}, 'defined-tags': {'module': 'os_management', 'class': 'dict(str, dict(str, object))'}}, output_type={'module': 'os_management', 'class': 'Event'}) +@cli_util.wrap_exceptions +def update_event(ctx, from_json, force, managed_instance_id, event_id, compartment_id, freeform_tags, defined_tags, if_match): + + if isinstance(managed_instance_id, six.string_types) and len(managed_instance_id.strip()) == 0: + raise click.UsageError('Parameter --managed-instance-id cannot be whitespace or empty string') + + if isinstance(event_id, six.string_types) and len(event_id.strip()) == 0: + raise click.UsageError('Parameter --event-id cannot be whitespace or empty string') + if not force: + if freeform_tags or defined_tags: + if not click.confirm("WARNING: Updates to freeform-tags and defined-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 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) + + client = cli_util.build_client('os_management', 'event', ctx) + result = client.update_event( + managed_instance_id=managed_instance_id, + event_id=event_id, + compartment_id=compartment_id, + update_event_details=_details, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@event_content_group.command(name=cli_util.override('event.upload_event_content.command_name', 'upload'), help=u"""Upload the event content as a ZIP archive from the managed instance to the service \n[Command Reference](uploadEventContent)""") +@cli_util.option('--managed-instance-id', required=True, help=u"""Instance Oracle Cloud identifier (ocid)""") +@cli_util.option('--event-id', required=True, help=u"""Unique Event identifier (OCID)""") +@cli_util.option('--compartment-id', required=True, help=u"""The ID of the compartment in which to list resources.""") +@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.""") +@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 upload_event_content(ctx, from_json, managed_instance_id, event_id, compartment_id, if_match): + + if isinstance(managed_instance_id, six.string_types) and len(managed_instance_id.strip()) == 0: + raise click.UsageError('Parameter --managed-instance-id cannot be whitespace or empty string') + + if isinstance(event_id, six.string_types) and len(event_id.strip()) == 0: + raise click.UsageError('Parameter --event-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('os_management', 'event', ctx) + result = client.upload_event_content( + managed_instance_id=managed_instance_id, + event_id=event_id, + compartment_id=compartment_id, + **kwargs + ) + cli_util.render_response(result, ctx) diff --git a/services/os_management/src/oci_cli_os_management/generated/os_management_service_cli.py b/services/os_management/src/oci_cli_os_management/generated/os_management_service_cli.py new file mode 100644 index 000000000..1840154ed --- /dev/null +++ b/services/os_management/src/oci_cli_os_management/generated/os_management_service_cli.py @@ -0,0 +1,14 @@ +# coding: utf-8 +# Copyright (c) 2016, 2021, 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. + +from oci_cli.cli_root import cli +from oci_cli import cli_util +from oci_cli.aliasing import CommandGroupWithAlias + + +@cli.command(cli_util.override('os_management.os_management_service_group.command_name', 'os-management'), cls=CommandGroupWithAlias, help=cli_util.override('os_management.os_management_service_group.help', """API for the OS Management service. Use these API operations for working +with Managed instances and Managed instance groups."""), short_help=cli_util.override('os_management.os_management_service_group.short_help', """OS Management API""")) +@cli_util.help_option_group +def os_management_service_group(): + pass diff --git a/services/os_management/src/oci_cli_os_management/generated/osmanagement_cli.py b/services/os_management/src/oci_cli_os_management/generated/osmanagement_cli.py index 028b71f46..aa31e85d3 100644 --- a/services/os_management/src/oci_cli_os_management/generated/osmanagement_cli.py +++ b/services/os_management/src/oci_cli_os_management/generated/osmanagement_cli.py @@ -7,15 +7,15 @@ 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 +from services.os_management.src.oci_cli_os_management.generated import os_management_service_cli -@cli.command(cli_util.override('os_management.os_management_root_group.command_name', 'os-management'), cls=CommandGroupWithAlias, help=cli_util.override('os_management.os_management_root_group.help', """API for the OS Management service. Use these API operations for working +@click.command(cli_util.override('os_management.os_management_root_group.command_name', 'os-management'), cls=CommandGroupWithAlias, help=cli_util.override('os_management.os_management_root_group.help', """API for the OS Management service. Use these API operations for working with Managed instances and Managed instance groups."""), short_help=cli_util.override('os_management.os_management_root_group.short_help', """OS Management API""")) @cli_util.help_option_group def os_management_root_group(): @@ -58,6 +58,12 @@ def windows_update_group(): pass +@click.command(cli_util.override('os_management.update_managed_instance_details_group.command_name', 'update-managed-instance-details'), cls=CommandGroupWithAlias, help="""Information to update a managed instance""") +@cli_util.help_option_group +def update_managed_instance_details_group(): + pass + + @click.command(cli_util.override('os_management.work_request_summary_group.command_name', 'work-request-summary'), cls=CommandGroupWithAlias, help="""A work request summary""") @cli_util.help_option_group def work_request_summary_group(): @@ -76,15 +82,29 @@ def erratum_summary_group(): pass +os_management_service_cli.os_management_service_group.add_command(os_management_root_group) os_management_root_group.add_command(software_source_group) os_management_root_group.add_command(erratum_group) os_management_root_group.add_command(managed_instance_group_group) os_management_root_group.add_command(managed_instance_group) os_management_root_group.add_command(scheduled_job_group) os_management_root_group.add_command(windows_update_group) +os_management_root_group.add_command(update_managed_instance_details_group) os_management_root_group.add_command(work_request_summary_group) os_management_root_group.add_command(work_request_group) os_management_root_group.add_command(erratum_summary_group) +# oci os_management os_management --> oci os_management +os_management_service_cli.os_management_service_group.commands.pop(os_management_root_group.name) +os_management_service_cli.os_management_service_group.add_command(software_source_group) +os_management_service_cli.os_management_service_group.add_command(erratum_group) +os_management_service_cli.os_management_service_group.add_command(managed_instance_group_group) +os_management_service_cli.os_management_service_group.add_command(managed_instance_group) +os_management_service_cli.os_management_service_group.add_command(scheduled_job_group) +os_management_service_cli.os_management_service_group.add_command(windows_update_group) +os_management_service_cli.os_management_service_group.add_command(update_managed_instance_details_group) +os_management_service_cli.os_management_service_group.add_command(work_request_summary_group) +os_management_service_cli.os_management_service_group.add_command(work_request_group) +os_management_service_cli.os_management_service_group.add_command(erratum_summary_group) @software_source_group.command(name=cli_util.override('os_management.add_packages_to_software_source.command_name', 'add'), help=u"""Adds a given list of Software Packages to a specific Software Source. \n[Command Reference](addPackagesToSoftwareSource)""") @@ -376,7 +396,7 @@ def create_managed_instance_group(ctx, from_json, wait_for_state, max_wait_secon @cli_util.option('--managed-instance-groups', type=custom_types.CLI_COMPLEX_TYPE, help=u"""The list of managed instance groups this scheduled job operates on (mutually exclusive with managedInstances). Either this or managedInstances must be supplied. This option is a JSON list with items of type Id. For documentation on Id please see our API reference: https://docs.cloud.oracle.com/api/#/en/osmanagement/20190801/datatypes/Id.""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) -@cli_util.option('--update-type', type=custom_types.CliCaseInsensitiveChoice(["SECURITY", "BUGFIX", "ENHANCEMENT", "ALL"]), help=u"""Type of the update (only if operation type is UPDATEALL)""") +@cli_util.option('--update-type', type=custom_types.CliCaseInsensitiveChoice(["SECURITY", "BUGFIX", "ENHANCEMENT", "OTHER", "KSPLICE", "ALL"]), help=u"""Type of the update (only if operation type is UPDATEALL)""") @cli_util.option('--package-names', type=custom_types.CLI_COMPLEX_TYPE, help=u"""the id of the package (only if operation type is INSTALL/UPDATE/REMOVE) This option is a JSON list with items of type PackageName. For documentation on PackageName please see our API reference: https://docs.cloud.oracle.com/api/#/en/osmanagement/20190801/datatypes/PackageName.""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) @@ -1008,6 +1028,7 @@ def get_work_request(ctx, from_json, work_request_id): @managed_instance_group.command(name=cli_util.override('os_management.install_all_package_updates_on_managed_instance.command_name', 'install-all-package-updates'), help=u"""Install all of the available package updates for the managed instance. \n[Command Reference](installAllPackageUpdatesOnManagedInstance)""") @cli_util.option('--managed-instance-id', required=True, help=u"""OCID for the managed instance""") +@cli_util.option('--update-type', type=custom_types.CliCaseInsensitiveChoice(["SECURITY", "BUGFIX", "ENHANCEMENT", "OTHER", "KSPLICE", "ALL"]), help=u"""The type of updates to be applied""") @cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "FAILED", "SUCCEEDED", "CANCELLING", "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 SUCCEEDED --wait-for-state FAILED 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 to see if it has reached the state defined by --wait-for-state. Defaults to 30 seconds.""") @@ -1016,12 +1037,14 @@ def get_work_request(ctx, from_json, work_request_id): @click.pass_context @json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}) @cli_util.wrap_exceptions -def install_all_package_updates_on_managed_instance(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, managed_instance_id): +def install_all_package_updates_on_managed_instance(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, managed_instance_id, update_type): if isinstance(managed_instance_id, six.string_types) and len(managed_instance_id.strip()) == 0: raise click.UsageError('Parameter --managed-instance-id cannot be whitespace or empty string') kwargs = {} + if update_type is not None: + kwargs['update_type'] = update_type kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) client = cli_util.build_client('os_management', 'os_management', ctx) result = client.install_all_package_updates_on_managed_instance( @@ -1054,8 +1077,60 @@ def install_all_package_updates_on_managed_instance(ctx, from_json, wait_for_sta cli_util.render_response(result, ctx) +@managed_instance_group_group.command(name=cli_util.override('os_management.install_all_updates_on_managed_instance_group.command_name', 'install-all-updates'), help=u"""Install all of the available updates for the Managed Instance Group. \n[Command Reference](installAllUpdatesOnManagedInstanceGroup)""") +@cli_util.option('--managed-instance-group-id', required=True, help=u"""OCID for the managed instance group""") +@cli_util.option('--update-type', type=custom_types.CliCaseInsensitiveChoice(["SECURITY", "BUGFIX", "ENHANCEMENT", "OTHER", "KSPLICE", "ALL"]), help=u"""The type of updates to be applied""") +@cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "FAILED", "SUCCEEDED", "CANCELLING", "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 SUCCEEDED --wait-for-state FAILED 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 to see if it 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 install_all_updates_on_managed_instance_group(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, managed_instance_group_id, update_type): + + if isinstance(managed_instance_group_id, six.string_types) and len(managed_instance_group_id.strip()) == 0: + raise click.UsageError('Parameter --managed-instance-group-id cannot be whitespace or empty string') + + kwargs = {} + if update_type is not None: + kwargs['update_type'] = update_type + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + client = cli_util.build_client('os_management', 'os_management', ctx) + result = client.install_all_updates_on_managed_instance_group( + managed_instance_group_id=managed_instance_group_id, + **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 + + 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) + + @managed_instance_group.command(name=cli_util.override('os_management.install_all_windows_updates_on_managed_instance.command_name', 'install-all-windows-updates'), help=u"""Install all of the available Windows updates for the managed instance. \n[Command Reference](installAllWindowsUpdatesOnManagedInstance)""") @cli_util.option('--managed-instance-id', required=True, help=u"""OCID for the managed instance""") +@cli_util.option('--update-type', type=custom_types.CliCaseInsensitiveChoice(["SECURITY", "BUGFIX", "ENHANCEMENT", "OTHER", "KSPLICE", "ALL"]), help=u"""The type of updates to be applied""") @cli_util.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "FAILED", "SUCCEEDED", "CANCELLING", "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 SUCCEEDED --wait-for-state FAILED 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 to see if it has reached the state defined by --wait-for-state. Defaults to 30 seconds.""") @@ -1064,12 +1139,14 @@ def install_all_package_updates_on_managed_instance(ctx, from_json, wait_for_sta @click.pass_context @json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}) @cli_util.wrap_exceptions -def install_all_windows_updates_on_managed_instance(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, managed_instance_id): +def install_all_windows_updates_on_managed_instance(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, managed_instance_id, update_type): if isinstance(managed_instance_id, six.string_types) and len(managed_instance_id.strip()) == 0: raise click.UsageError('Parameter --managed-instance-id cannot be whitespace or empty string') kwargs = {} + if update_type is not None: + kwargs['update_type'] = update_type kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) client = cli_util.build_client('os_management', 'os_management', ctx) result = client.install_all_windows_updates_on_managed_instance( @@ -1857,6 +1934,7 @@ def list_packages_installed_on_managed_instance(ctx, from_json, all_pages, page_ @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('--lifecycle-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "UPDATING", "ACTIVE", "DELETING", "DELETED", "FAILED"]), help=u"""The current lifecycle state for the object.""") @cli_util.option('--os-family', type=custom_types.CliCaseInsensitiveChoice(["LINUX", "WINDOWS", "ALL"]), help=u"""The OS family for which to list resources.""") +@cli_util.option('--is-restricted', type=click.BOOL, help=u"""If true, will only filter out restricted Autonomous Linux Scheduled Job""") @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({}) @@ -1864,7 +1942,7 @@ def list_packages_installed_on_managed_instance(ctx, from_json, all_pages, page_ @click.pass_context @json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}, output_type={'module': 'os_management', 'class': 'list[ScheduledJobSummary]'}) @cli_util.wrap_exceptions -def list_scheduled_jobs(ctx, from_json, all_pages, page_size, compartment_id, display_name, managed_instance_id, managed_instance_group_id, operation_type, limit, page, sort_order, sort_by, lifecycle_state, os_family): +def list_scheduled_jobs(ctx, from_json, all_pages, page_size, compartment_id, display_name, managed_instance_id, managed_instance_group_id, operation_type, limit, page, sort_order, sort_by, lifecycle_state, os_family, is_restricted): if all_pages and limit: raise click.UsageError('If you provide the --all option you cannot provide the --limit option') @@ -1890,6 +1968,8 @@ def list_scheduled_jobs(ctx, from_json, all_pages, page_size, compartment_id, di kwargs['lifecycle_state'] = lifecycle_state if os_family is not None: kwargs['os_family'] = os_family + if is_restricted is not None: + kwargs['is_restricted'] = is_restricted kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) client = cli_util.build_client('os_management', 'os_management', ctx) if all_pages: @@ -2591,6 +2671,43 @@ def skip_next_scheduled_job_execution(ctx, from_json, scheduled_job_id, if_match cli_util.render_response(result, ctx) +@update_managed_instance_details_group.command(name=cli_util.override('os_management.update_managed_instance.command_name', 'update-managed-instance'), help=u"""Updates a specific Managed Instance. \n[Command Reference](updateManagedInstance)""") +@cli_util.option('--managed-instance-id', required=True, help=u"""OCID for the managed instance""") +@cli_util.option('--notification-topic-id', help=u"""OCID of the ONS topic used to send notification to users""") +@cli_util.option('--is-data-collection-authorized', type=click.BOOL, help=u"""True if user allow data collection for this instance""") +@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.""") +@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': 'os_management', 'class': 'ManagedInstance'}) +@cli_util.wrap_exceptions +def update_managed_instance(ctx, from_json, managed_instance_id, notification_topic_id, is_data_collection_authorized, if_match): + + if isinstance(managed_instance_id, six.string_types) and len(managed_instance_id.strip()) == 0: + raise click.UsageError('Parameter --managed-instance-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']) + + _details = {} + + if notification_topic_id is not None: + _details['notificationTopicId'] = notification_topic_id + + if is_data_collection_authorized is not None: + _details['isDataCollectionAuthorized'] = is_data_collection_authorized + + client = cli_util.build_client('os_management', 'os_management', ctx) + result = client.update_managed_instance( + managed_instance_id=managed_instance_id, + update_managed_instance_details=_details, + **kwargs + ) + cli_util.render_response(result, ctx) + + @managed_instance_group_group.command(name=cli_util.override('os_management.update_managed_instance_group.command_name', 'update'), help=u"""Updates a specific Managed Instance Group. \n[Command Reference](updateManagedInstanceGroup)""") @cli_util.option('--managed-instance-group-id', required=True, help=u"""OCID for the managed instance group""") @cli_util.option('--display-name', help=u"""Managed Instance Group identifier""") @@ -2676,7 +2793,7 @@ def update_managed_instance_group(ctx, from_json, force, wait_for_state, max_wai @cli_util.option('--interval-type', type=custom_types.CliCaseInsensitiveChoice(["HOUR", "DAY", "WEEK", "MONTH"]), help=u"""the interval period for a recurring Scheduled Job (only if schedule type is RECURRING)""") @cli_util.option('--interval-value', help=u"""the value for the interval period for a recurring Scheduled Job (only if schedule type is RECURRING)""") @cli_util.option('--operation-type', type=custom_types.CliCaseInsensitiveChoice(["INSTALL", "UPDATE", "REMOVE", "UPDATEALL"]), help=u"""the type of operation this Scheduled Job performs""") -@cli_util.option('--update-type', type=custom_types.CliCaseInsensitiveChoice(["SECURITY", "BUGFIX", "ENHANCEMENT", "ALL"]), help=u"""Type of the update (only if operation type is UPDATEALL)""") +@cli_util.option('--update-type', type=custom_types.CliCaseInsensitiveChoice(["SECURITY", "BUGFIX", "ENHANCEMENT", "OTHER", "KSPLICE", "ALL"]), help=u"""Type of the update (only if operation type is UPDATEALL)""") @cli_util.option('--package-names', type=custom_types.CLI_COMPLEX_TYPE, help=u"""the id of the package (only if operation type is INSTALL/UPDATE/REMOVE) This option is a JSON list with items of type PackageName. For documentation on PackageName please see our API reference: https://docs.cloud.oracle.com/api/#/en/osmanagement/20190801/datatypes/PackageName.""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) diff --git a/setup.py b/setup.py index 8430dc59b..a3411d2d8 100644 --- a/setup.py +++ b/setup.py @@ -29,12 +29,11 @@ def open_relative(*path): readme = f.read() requires = [ - 'oci==2.44.1', - 'arrow==0.17.0', + 'oci==2.44.2', + 'arrow>=1.0.0', 'certifi', 'click==7.1.2', - 'configparser==4.0.2', - 'cryptography>3.2.1,<=3.4.7', + 'cryptography>=3.2.1,<=3.4.7', 'jmespath==0.10.0', 'python-dateutil>=2.5.3,<3.0.0', 'pytz>=2016.10', diff --git a/src/oci_cli/cli_util.py b/src/oci_cli/cli_util.py index a030dddb6..1d1d1d70d 100644 --- a/src/oci_cli/cli_util.py +++ b/src/oci_cli/cli_util.py @@ -339,21 +339,27 @@ def create_config_and_signer_based_on_click_context(ctx): except exceptions.ConfigFileNotFound as e: # config file is not required to be present for instance principal auth or resource principal auth if not (instance_principal_auth or resource_principal_auth): - # if user requests session authentication without a config file, prompt them to create a session profile - if session_token_auth: - click.echo('ERROR: Could not find config file at {}'.format(os.path.expanduser(ctx.obj['config_file']))) - if click.confirm('Do you want to create a new config file with a CLI session profile that can be used with --auth {}?'.format(cli_constants.OCI_CLI_AUTH_SESSION_TOKEN), default=True): - from .cli_session import authenticate - ctx.invoke(authenticate, profile_name=ctx.obj['profile'], config_location=os.path.expanduser(ctx.obj['config_file'])) - # if there are any issues with the authentication, they should be handled by the session authenticate process itself - # so these lines below will only be reached if the session authenticate command finished successfully - click.echo('Successfully created config file {} with your new CLI session profile {}'.format(os.path.expanduser(ctx.obj['config_file']), ctx.obj['profile'])) - click.echo('You can now re-run your command to use your new session profile') - sys.exit(0) - else: - sys.exit(1) + click.echo('ERROR: Could not find config file at {}'.format(os.path.expanduser(ctx.obj['config_file']))) + # if user requests session authentication without a config file, prompt them to create a config file with a session profile + # otherwise, prompt them to create the config file with a profile that uses API key pair authentication + if session_token_auth and click.confirm('Do you want to create a new config file with a CLI session profile that can be used with --auth {}?'.format(cli_constants.OCI_CLI_AUTH_SESSION_TOKEN), default=True): + from .cli_session import authenticate + ctx.invoke(authenticate, profile_name=ctx.obj['profile'], config_location=os.path.expanduser(ctx.obj['config_file'])) + # if there are any issues with the authentication, they should be handled by the session authenticate process itself + # so these lines below will only be reached if the session authenticate command finished successfully + click.echo('Successfully created config file {} with your new CLI session profile {}'.format(os.path.expanduser(ctx.obj['config_file']), ctx.obj['profile'])) + click.echo('You can now re-run your command to use your new session profile') + sys.exit(0) + elif (not session_token_auth) and click.confirm('Do you want to create a new config file?', default=True): + from .cli_setup import generate_oci_config + ctx.invoke(generate_oci_config) + # if there are any issues with the config setup, they should be handled by the setup config process itself + # so these lines below will only be reached if the setup config command finished successfully + click.echo('Successfully created config file with your new CLI user profile') + click.echo('Once you have uploaded your public key through the console (instructions above), you can re-run your command to use your new config file and user profile') + sys.exit(0) else: - sys.exit("ERROR: " + str(e)) + sys.exit(1) client_config["additional_user_agent"] = 'Oracle-PythonCLI/{}'.format(__version__) if ctx.obj['debug']: client_config["log_requests"] = True diff --git a/src/oci_cli/version.py b/src/oci_cli/version.py index bafeb6498..0d8f24a44 100644 --- a/src/oci_cli/version.py +++ b/src/oci_cli/version.py @@ -2,4 +2,4 @@ # Copyright (c) 2016, 2021, 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.0.2' +__version__ = '3.0.3' diff --git a/tests/test_config_validation.py b/tests/test_config_validation.py index 34160912a..2e52d09b4 100644 --- a/tests/test_config_validation.py +++ b/tests/test_config_validation.py @@ -217,6 +217,61 @@ def test_auth_security_token_with_expired_session(runner): os.environ['OCI_CLI_CONFIG_FILE'] = 'internal_resources/config' +def test_command_with_no_config(runner): + try: + # create a temporary config file path that will be treated as the default config that does not exist + temp_dir = tempfile.mkdtemp() + oci_cli.cli_setup.DEFAULT_DIRECTORY = temp_dir + config_file = os.path.join(temp_dir, 'config') + oci_cli.cli_setup.DEFAULT_CONFIG_LOCATION = config_file + os.environ['OCI_CLI_CONFIG_FILE'] = config_file + + test_ocid = 'ocid1.user.oc1..aaaaaaaa4vxfovwygtyjlqczmn6ju3korktidzlk6auw6c4tgsug5brc2ekq' + test_tenancy = 'ocid1.tenancy.oc1..aaaaaaaa3vi3ft3yi3sq4nhiql4nvbzjz6gipbn72h7werl6njs6xsq4wgdq' + region = 'us-phoenix-1' + + # make sure config file does not exist yet + assert not os.path.exists(config_file) + + stdin = [ + 'n', # choose not to create new config file + ] + + # test CLI command with no config file, and choose not to create new config file + result = invoke_example_operation(runner, config_file, 'DEFAULT', command_input='\n'.join(stdin)) + assert 'Could not find config file' in result.output + assert result.exit_code == 1 + + stdin = [ + 'Y', # choose to create new config file + config_file, # location for the new config file + test_ocid, + test_tenancy, + region, + 'Y', # generate new key pair + temp_dir, # directory for the keys + 'oci_api_key', + '', # no private key passphrase + ] + + # test CLI command with no config file, and choose to create new config file + result = invoke_example_operation(runner, config_file, 'DEFAULT', command_input='\n'.join(stdin)) + assert 'Could not find config file' in result.output + assert 'Do you want to create a new config file' in result.output + assert 'Config written to' in result.output + assert result.exit_code == 0 + + # make sure config file now exists + assert os.path.exists(config_file) + + # test CLI command with security_token auth and existing config file, and make sure new config file prompt does not appear + result = invoke_example_operation(runner, config_file, 'DEFAULT', ['--auth', 'security_token'], command_input='\n'.join(stdin)) + assert 'Could not find config file' not in result.output + finally: + shutil.rmtree(temp_dir) + os.environ['OCI_CLI_CONFIG_FILE'] = 'internal_resources/config' + + def validate_missing_param_error(result, key, message): assert 1 == result.exit_code assert message in result.output diff --git a/tests/test_root_options.py b/tests/test_root_options.py index a574105ff..e6fe30872 100644 --- a/tests/test_root_options.py +++ b/tests/test_root_options.py @@ -99,7 +99,7 @@ def test_rc_file_location_environment_variable(runner, config_file): def test_config_file_location_environment_variable(runner, config_file): original_value = os.environ[oci_cli.cli_constants.OCI_CLI_CONFIG_FILE_ENV_VAR] os.environ[oci_cli.cli_constants.OCI_CLI_CONFIG_FILE_ENV_VAR] = 'tests/invalid_config' - result = invoke_example_operation(runner, [], None) + result = invoke_example_operation(runner, [], None, command_input='n') del os.environ[oci_cli.cli_constants.OCI_CLI_CONFIG_FILE_ENV_VAR] assert 1 == result.exit_code assert 'tests/invalid_config' in result.output @@ -118,7 +118,7 @@ def test_config_values_from_environment_variable_mock_config(runner, config_file original_value = os.environ[oci_cli.cli_constants.OCI_CLI_CONFIG_FILE_ENV_VAR] os.environ[oci_cli.cli_constants.OCI_CLI_CONFIG_FILE_ENV_VAR] = 'tests/invalid_config' - result = invoke_example_operation(runner, [], None) + result = invoke_example_operation(runner, [], None, command_input='n') assert 1 == result.exit_code # restore OCI_CLI_CONFIG_FILE env variable env variable as it used in other tests. @@ -215,9 +215,9 @@ def teardown_module(module): six.moves.http_client.HTTPConnection.debuglevel = 0 -def invoke_example_operation(runner, root_args, config_file): +def invoke_example_operation(runner, root_args, config_file, command_input=None): args = root_args + (['--config-file', config_file] if config_file else []) + ['os', 'ns', 'get'] - return runner.invoke(oci_cli.cli, args) + return runner.invoke(oci_cli.cli, args, input=command_input) # Copies the env vars which are required to mock a config and removes them