diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..4692276de --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +.idea +*.iml +*.egg-info +.tox/ +.python-version +*.pyc +*.swp +build/ +dist/ +env/ +*.egg-info/ +*.zip +.DS_STORE +data/ +docs/warnings.txt +docs/process_sources_warnings.txt +docs/_build/ +src/oci_cli/help_text_producer/data_files/man +src/oci_cli/help_text_producer/data_files/text +scripts/temp/ +target/ +tests/resources/content_output.txt +tests/output/console_history_output.txt +tests/temp +.cache/ +.project +.wercker/ diff --git a/CHANGELOG.rst b/CHANGELOG.rst index cef422ab2..02aa25df2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,6 +7,20 @@ All notable changes to this project will be documented in this file. The format is based on `Keep a Changelog `__. +2.4.17 - 2018-02-22 +--------------------- +Added +~~~~~~~~~~ +* Added support for the File Storage Service. (``oci fs``) +* Added support for Path Route Sets in the Load Balancer Service. An example can be found on `Github `_ (``oci lb path-route-set``) +* Added tagging support for *Bucket* resources in the Object Storage Service + * Create a bucket with tags: ``oci os bucket create --defined-tags --freeform-tags`` + * Update a bucket with tags: ``oci os bucket update --defined-tags --freeform-tags`` + * List buckets and display defined and freeform tags in the results: ``oci os bucket list --fields tags`` +* Added support for specifying a restore period for archived objects in the *RestoreObjects* operation of the Object Storage service. (``oci os object restore --hours``) +* Added support for filtering by *backupId* in *ListDbSystems* operation in the Database Service (``oci db system list --backup-id``) +* Added support for getting plink (the `PuTTY `_ command line interface) compatible instance console connection string for Windows users (``oci compute instance-console-connection get-plink-connection-string``) + 2.4.16 - 2018-02-08 --------------------- Added diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 875b3b37f..c9f2e82c7 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -1,7 +1,7 @@ Contributing to the Oracle Cloud Infrastructure CLI ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.* +*Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.* Pull requests can be made under `The Oracle Contributor Agreement `_ (OCA). diff --git a/requirements.txt b/requirements.txt index bbd85db6d..0d9ca853d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ Jinja2==2.9.6 jmespath==0.9.3 ndg-httpsclient==0.4.2 mock==2.0.0 -oci==1.3.14 +oci==1.3.15 packaging==16.8 pluggy==0.4.0 py==1.4.33 diff --git a/scripts/create_load_balancer.sh b/scripts/create_load_balancer.sh index e0e3e2db8..ec57fdfd3 100755 --- a/scripts/create_load_balancer.sh +++ b/scripts/create_load_balancer.sh @@ -3,7 +3,7 @@ # # - Creating a load balancer by providing all options at create time (e.g. certificates, listeners, backend sets) # - We also show two sub-variants: providing each option as an individual parameter (e.g. --certificiates, --listeners) and how to provide a consolidated -# set of options using --from-json +# set of options using --from-json # - Creating a load balancer by providing the minimum options at create time and then adding related resources (e.g. certificates, listeners, backend sets) # post-creation # @@ -43,7 +43,7 @@ echo "Load Balancer Shape: $LB_SHAPE" # This also provides each complex type as an individual option (e.g. --certificates, --listeners). It is also possible to provide these in a consolidated format, which is demonstrated # by the function create_lb_with_all_options_using_from_json function create_lb_with_all_options_as_individual_options() { - # certificates_with_comments.json contains a description of the parameter. Since valid JSON cannot contain comments, we use jsonlint (which was installed + # certificates_with_comments.json contains a description of the parameter. Since valid JSON cannot contain comments, we use jsonlint (which was installed # via our demjson dependency) to remove the comments and allow the CLI to use it. # # You should replace the values in certificates_with_comments.json with those appropriate for your use case (e.g. your own PEM-formatted strings) @@ -51,6 +51,10 @@ function create_lb_with_all_options_as_individual_options() { jsonlint -Sf scripts/create_load_balancer_example/backend_sets_with_comments.json > scripts/create_load_balancer_example/backend_sets.json jsonlint -Sf scripts/create_load_balancer_example/listeners_with_comments.json > scripts/create_load_balancer_example/listeners.json + # Path Route Sets are not mandatory parameter to load balancer. They enhance + # load balancer feature set by providing traffic routing flexibility. + # More info about the feature can be found in scripts/create_load_balancer_example/path_route_sets_with_comments.json + jsonlint -Sf scripts/create_load_balancer_example/path_route_sets_with_comments.json > scripts/create_load_balancer_example/path_route_sets.json # Subnets are passed as a JSON array where each entry is a subnet OCID. For example: # @@ -60,14 +64,14 @@ function create_lb_with_all_options_as_individual_options() { echo "[\"${FIRST_SUBNET_ID}\", \"${SECOND_SUBNET_ID}\"]" > scripts/create_load_balancer_example/subnets.json # Note here in our create we use --certificates, --listeners etc. to pass in each complex type - # + # # There is some implicit sequencing in that: # - The backend set information (--backend-sets) may need the name of the certificate bundle specified in --certificates # - The listener information (--listeners) needs the name of one of the backend sets in --backend-sets # - The listener information (--listeners) may need the name of the certificate bundle specified in --certificates # # So you need to take that into account when preparing your files for input - CREATED_LB=$(oci lb load-balancer create -c $COMPARTMENT_ID --display-name exampleLb --shape-name $LB_SHAPE --subnet-ids file://scripts/create_load_balancer_example/subnets.json --certificates file://scripts/create_load_balancer_example/certificates.json --backend-sets file://scripts/create_load_balancer_example/backend_sets.json --listeners file://scripts/create_load_balancer_example/listeners.json) + CREATED_LB=$(oci lb load-balancer create -c $COMPARTMENT_ID --display-name exampleLb --shape-name $LB_SHAPE --subnet-ids file://scripts/create_load_balancer_example/subnets.json --certificates file://scripts/create_load_balancer_example/certificates.json --backend-sets file://scripts/create_load_balancer_example/backend_sets.json --listeners file://scripts/create_load_balancer_example/listeners.json --path-route-sets file://scripts/create_load_balancer_example/path_route_sets.json) WORK_REQUEST_ID=$(jq -r '."opc-work-request-id"' <<< "$CREATED_LB") echo "Create Load Balancer Work Request ID: $WORK_REQUEST_ID" @@ -96,7 +100,7 @@ function create_lb_with_all_options_as_individual_options() { sleep 120 } -# We've seen in the create_lb_with_all_options_as_individual_options function that we can create a load balancer and provide complex parameters, such as --backend-sets, +# We've seen in the create_lb_with_all_options_as_individual_options function that we can create a load balancer and provide complex parameters, such as --backend-sets, # as separate options. However, rather than specifying complex parameters individually, we can supply them in a consolidated format - in this case by passing it in # as a single file to the --from-json option. # @@ -189,7 +193,19 @@ function create_lb_with_minimum_then_add_related_resources() { oci lb backend create --load-balancer-id $LB_ID --backend-set-name backendSetName --ip-address 10.10.10.4 --port 80 --weight 3 oci lb backend create --load-balancer-id $LB_ID --backend-set-name backendSetName --ip-address 10.10.10.5 --port 80 --weight 3 - # Now that we have our certificates and backend set, we can add a listener. We need to specify a backend set which exists (e.g. the one we made) + # We can create Path Route Sets now since we have our backend set created. + # Path Route Sets require backend sets to be mentioned as part of path route + # rules. A path route set includes all path route strings and matching rules + # that define the data routing for a particular listener. Path Route rules + # enable routing of traffic to correct backend set eliminating the need to + # create multiple listeners or load balancers to achieve the same. + oci lb path-route-set create --load-balancer-id $LB_ID \ + --name PathRouteSetName \ + --path-routes '[{"backendSetName":"backendSetName", "path":"/video", "pathMatchType":{"matchType":"EXACT_MATCH"}}]' \ + --wait-for-state SUCCEEDED \ + --max-wait-seconds 300 + + # Now that we have our certificates, backend set and path route set, we can add a listener. We need to specify a backend set which exists (e.g. the one we made) # # The valid values for --protocol can be found via "oci lb protocol list" # @@ -201,7 +217,8 @@ function create_lb_with_minimum_then_add_related_resources() { --protocol HTTP \ --ssl-certificate-name my_cert_bundle \ --ssl-verify-depth 3 \ - --ssl-verify-peer-certificate false + --ssl-verify-peer-certificate false \ + --path-route-set-name PathRouteSetName # Print out information about the load balancer oci lb load-balancer get --load-balancer-id $LB_ID @@ -220,4 +237,4 @@ oci network subnet delete --subnet-id $FIRST_SUBNET_ID --force --wait-for-state oci network subnet delete --subnet-id $SECOND_SUBNET_ID --force --wait-for-state TERMINATED # Delete the VCN -oci network vcn delete --vcn-id $VCN_ID --force --wait-for-state TERMINATED \ No newline at end of file +oci network vcn delete --vcn-id $VCN_ID --force --wait-for-state TERMINATED diff --git a/scripts/create_load_balancer_example/create_load_balancer_all_complex_params_with_comments.json b/scripts/create_load_balancer_example/create_load_balancer_all_complex_params_with_comments.json index f8c198808..555b66723 100644 --- a/scripts/create_load_balancer_example/create_load_balancer_all_complex_params_with_comments.json +++ b/scripts/create_load_balancer_example/create_load_balancer_all_complex_params_with_comments.json @@ -55,6 +55,20 @@ "defaultBackendSetName": "backendSetName", "port": 8080, "protocol": "HTTP" + "pathRouteSetName": "PathRouteSetName" + } + }, + "pathRouteSets": { + "PathRouteSetName": { + "pathRoutes": [ + { + "backendSetName": "backendSetName", + "path": "/video", + "pathMatchType": { + "matchType": "EXACT_MATCH" + } + } + ] } } -} \ No newline at end of file +} diff --git a/scripts/create_load_balancer_example/path_route_sets_with_comments.json b/scripts/create_load_balancer_example/path_route_sets_with_comments.json new file mode 100644 index 000000000..18dc99056 --- /dev/null +++ b/scripts/create_load_balancer_example/path_route_sets_with_comments.json @@ -0,0 +1,54 @@ +{ + /* + * Each entry in this dictionary represents a path route set which can be used + * by a load balancer. A path route set includes all path route strings and + * matching rules that define the data routing for a particular listener. + */ + "PathRouteSetName": { + /* A path route is a string that the Load Balancing service matches against + * an incoming URI to determine the appropriate destination backend set. A + * path route rule consists of a path route string and a pattern match type. + */ + /* For more information about each attribute and the feature, refer this link: + * https://docs.us-phoenix-1.oraclecloud.com/Content/Balance/Tasks/managingrequest.htm#path + */ + "pathRoutes": [ + { + // The backend set to which the traffic should be routed + "backendSetName": "backendSetName", + // The path string to be used for matching with the incoming HTTP/HTTPS URI + // The unique part of the URI e.g. /video, /data, etc. + "path": "/video", + // Rule match type. Pick one option from below link: + // https://docs.us-phoenix-1.oraclecloud.com/api/#/en/loadbalancer/20170115/requests/PathMatchType + "pathMatchType": { + "matchType": "EXACT_MATCH" + } + } + ] + } + // Uncomment the below (and change information as needed) to add another path + // route set when creating the load balancer. You could copy it as many times + // as necessary to add all the path route stes you need + /* + , "PathRouteSetName2": { + // A path route set can have more than one path routes. A maximum of 20 are allowed. + "pathRoutes": [ + { + "backendSetName": "mySecondBackendSetName", + "path": "/cgi", + "pathMatchType": { + "matchType": "FORCE_LONGEST_PREFIX_MATCH" + } + }, + { + "backendSetName": "myThirdBackendSetName", + "path": "/data", + "pathMatchType": { + "matchType": "SUFFIX_MATCH" + } + } + ] + } + */ +} diff --git a/scripts/file_storage_example.sh b/scripts/file_storage_example.sh new file mode 100755 index 000000000..6b6ef84c4 --- /dev/null +++ b/scripts/file_storage_example.sh @@ -0,0 +1,166 @@ +#!/bin/bash +# This script provides a basic example of how to use the File Storage service in the CLI. +# The two variables at the beginning of the script must be specified accordingly: +# +# * COMPARTMENT_ID: The OCID of the compartment where we'll create our file system and related resources +# * AVAILABILITY_DOMAIN: The availability domain, e.g. Uocm:PHX-AD-1, where we'll create our file system and related resources +# +# The script will demonstrate: +# +# * Creating a new file system +# * Creating a mount target via which the file system can be accessed. The mount target and file system must +# be in the same availability domain in order to export the file system from the mount target +# * Creating an export so that we can mount the file system (see +# https://docs.us-phoenix-1.oraclecloud.com/Content/File/Tasks/mountingfilesystems.htm for more information) +# * Creating a snapshot of the file system +# +# In order to demonstrate functionality for mount targets and export sets, this script will also create a VCN +# and subnet. These will be deleted at the end of the script. +# +# Requirements for running this script: +# - OCI CLI v2.4.17 or later (you can check this by running oci --version) +# - jq (https://stedolan.github.io/jq/) for JSON querying of CLI output. This may be a useful utility in general and may help cater to scenarios +# which can't be wholly addressed by the --query option in the CLI + +set -e + +COMPARTMENT_ID="" +AVAILABILITY_DOMAIN="" + +# First we will create a VCN and a subnet. Since these resources have a lifecycle state, we can create them and use +# the --wait-for-state option so that our command will only return/complete when the resouce enters the desired +# state (in this case AVAILABLE) +CREATED_VCN=$(oci network vcn create -c $COMPARTMENT_ID --display-name createFsExampleVcn --cidr-block 10.0.0.0/16 --dns-label createFsExample --wait-for-state AVAILABLE 2>/dev/null) +VCN_ID=$(jq -r '.data.id' <<< "$CREATED_VCN") +echo "VCN OCID: ${VCN_ID}" + +CREATED_SUBNET=$(oci network subnet create -c $COMPARTMENT_ID --availability-domain $AVAILABILITY_DOMAIN --display-name createFsSubnet --vcn-id $VCN_ID --dns-label subnetFs --cidr-block 10.0.0.0/24 --wait-for-state AVAILABLE 2>/dev/null) +SUBNET_ID=$(jq -r '.data.id' <<< "$CREATED_SUBNET") +echo "Subnet OCID: $SUBNET_ID" +echo "" + +# First we create a file system. A file system has a lifecycle state so we can use the --wait-for-state +# option so that our command will only return/complete when the file system reaches the desired state. +CREATED_FILE_SYSTEM=$(oci fs file-system create -c $COMPARTMENT_ID --availability-domain $AVAILABILITY_DOMAIN --display-name exampleFileSystem --wait-for-state ACTIVE) +FILE_SYSTEM_ID=$(jq -r '.data.id' <<< "$CREATED_FILE_SYSTEM") +echo "File System OCID: $FILE_SYSTEM_ID" +echo "" + +# We can list file systems. This is a paginated call and we can use the --all option to get +# all results rather than having to manually deal with page tokens +echo "Listing all file systems" +echo "=========================" +oci fs file-system list -c $COMPARTMENT_ID --availability-domain $AVAILABILITY_DOMAIN --all +echo "" + +# We can retrieve the file system +echo "Retrieve file system" +echo "=========================" +oci fs file-system get --file-system-id $FILE_SYSTEM_ID +echo "" + +# Here we create a mount target. A couple of things to note: +# +# - If we don't specify a --hostname for the mount target then it can only be accessed via its private IP address +# - If we don't specify an --ip-address then one will be assigned from the free private IPs in the subnet +# - A mount target has a lifecycle state, so we can use --wait-for-state so that the command will only return/complete when the +# mount target reaches the desired state +CREATED_MOUNT_TARGET=$(oci fs mount-target create -c $COMPARTMENT_ID --availability-domain $AVAILABILITY_DOMAIN --subnet-id $SUBNET_ID --display-name exampleMountTarget --wait-for-state ACTIVE) +MOUNT_TARGET_ID=$(jq -r '.data.id' <<< "$CREATED_MOUNT_TARGET") +echo "Mount Target OCID: $FILE_SYSTEM_ID" +echo "" + +# We can list file systems. This is a paginated call and we can use the --all option to get +# all results rather than having to manually deal with page tokens +echo "Listing all mount targets" +echo "=========================" +oci fs mount-target list -c $COMPARTMENT_ID --availability-domain $AVAILABILITY_DOMAIN --all +echo "" + +# We can retrieve the mount target +echo "Retrieve mount target" +echo "=========================" +oci fs mount-target get --mount-target-id $MOUNT_TARGET_ID +echo "" + +# If we want to find the IP address via which a mount target can be accessed then we need to pull the private +# IP OCIDs (this is an array) from the mount target and then retrieve the information about the private IP by its +# OCID +PRIVATE_IP_ID=$(oci fs mount-target get --mount-target-id $MOUNT_TARGET_ID | jq -r '.data."private-ip-ids"[0]') +echo "Private IP OCID: $PRIVATE_IP_ID" +PRIVATE_IP=$(oci network private-ip get --private-ip-id $PRIVATE_IP_ID | jq -r '.data."ip-address"') +echo "Private IP Address: $PRIVATE_IP" +echo "" + +# A mount target contains an export set, which we can use to link the mount target to the file system. We do this +# by creating an export that links the export set and the file system. Once we have an export, we can access the +# file system via the mount target and the file system can be mounted on, say, a compute instance. +# +# For more information on mounting file systems see: +# https://docs.us-phoenix-1.oraclecloud.com/Content/File/Tasks/mountingfilesystems.htm +EXPORT_SET_ID=$(jq -r '.data."export-set-id"' <<< "$CREATED_MOUNT_TARGET") +CREATED_EXPORT=$(oci fs export create --file-system-id $FILE_SYSTEM_ID --export-set-id $EXPORT_SET_ID --wait-for-state ACTIVE --path /files) +EXPORT_ID=$(jq -r '.data.id' <<< "$CREATED_EXPORT") +echo "Export OCID: $EXPORT_ID" +echo "" + +# We can list exports. This operation also takes optional filters so we can narrow this list down by file system +# or export set (mount target). +echo "Listing Exports By File System" +echo "===============================" +oci fs export list -c $COMPARTMENT_ID --file-system-id $FILE_SYSTEM_ID --all +echo "" + +echo "Listing Exports By Export Set" +echo "===============================" +oci fs export list -c $COMPARTMENT_ID --export-set-id $EXPORT_SET_ID --all +echo "" + +# We can also view information on the export set itself +echo "Export Set Info" +echo "=================" +oci fs export-set get --export-set-id $EXPORT_SET_ID +echo "" + +# We can create a point-in-time snapshot of a file system. Snapshots also have a lifecycle state, so we can wait on it +# to become available +# +# Note that snapshot names are immutable and must be unique amongst all non-DELETED snapshots for a file system. +CREATED_SNAPSHOT=$(oci fs snapshot create --file-system-id $FILE_SYSTEM_ID --name exampleSnapshot --wait-for-state ACTIVE) +SNAPSHOT_ID=$(jq -r '.data.id' <<< "$CREATED_SNAPSHOT") +echo "Snapshot OCID: $SNAPSHOT_ID" +echo "" + +# We can list all snapshots in a file system +echo "Listing Snapshots By File System" +echo "=================================" +oci fs snapshot list --file-system-id $FILE_SYSTEM_ID --all +echo "" + +# Now clean up resources. Since these resources have lifecycle states, we can use --wait-for-state so that the command +# only completes/returns when the resource has entered the DELETED (or equivalent) state +oci fs snapshot delete --snapshot-id $SNAPSHOT_ID --force --wait-for-state DELETED +echo "Deleted Snapshot" + +oci fs export delete --export-id $EXPORT_ID --force --wait-for-state DELETED +echo "Deleted Export" + +oci fs mount-target delete --mount-target-id $MOUNT_TARGET_ID --force --wait-for-state DELETED +echo "Deleted Mount Target" + +oci fs file-system delete --file-system-id $FILE_SYSTEM_ID --force --wait-for-state DELETED +echo "Deleted File System" + +# Sometimes we can't delete the subnet straight after a mount target has been deleted as network resources +# still need to clear. To account for this in our script, put in a sleep +echo "Sleep for 60 seconds after mount target deletion before trying to delete the subnet" +sleep 60 + +oci network subnet delete --subnet-id $SUBNET_ID --force --wait-for-state TERMINATED +echo "Deleted Subnet" + +oci network vcn delete --vcn-id $VCN_ID --force --wait-for-state TERMINATED +echo "Deleted VCN" +echo "" + +echo "Script Finished" diff --git a/setup.py b/setup.py index e91df8347..65914529c 100644 --- a/setup.py +++ b/setup.py @@ -30,7 +30,7 @@ def open_relative(*path): requires = [ - 'oci==1.3.14', + 'oci==1.3.15', 'arrow==0.10.0', 'certifi', 'click==6.7', diff --git a/src/oci_cli/__init__.py b/src/oci_cli/__init__.py index 0d6222c43..ca97b96a5 100644 --- a/src/oci_cli/__init__.py +++ b/src/oci_cli/__init__.py @@ -11,6 +11,7 @@ from .generated import compute_cli # noqa: F401 from .generated import database_cli # noqa: F401 from .generated import dns_cli # noqa: F401 +from .generated import filestorage_cli # noqa: F401 from .generated import identity_cli # noqa: F401 from .generated import loadbalancer_cli # noqa: F401 from .generated import objectstorage_cli # noqa: F401 @@ -23,6 +24,7 @@ from . import dns_cli_extended # noqa: F401 from . import identity_cli_extended # noqa: F401 from . import objectstorage_cli_extended # noqa: F401 +from . import filestorage_cli_extended # noqa: F401 from . import file_filters # noqa: F401 from . import final_command_processor # noqa: F401 from . import lb_cli_extended # noqa: F401 diff --git a/src/oci_cli/bin/OciTabExpansion.ps1 b/src/oci_cli/bin/OciTabExpansion.ps1 index f58c2f27c..432e61992 100644 --- a/src/oci_cli/bin/OciTabExpansion.ps1 +++ b/src/oci_cli/bin/OciTabExpansion.ps1 @@ -1,7 +1,7 @@ # Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. $ociTopLevelCommands = @( - 'audit', 'bv', 'compute', 'db', 'dns', 'iam', 'lb', 'network', 'os', 'setup' + 'audit', 'bv', 'compute', 'db', 'dns', 'fs', 'iam', 'lb', 'network', 'os', 'setup' ) $ociSubcommands = @{ @@ -21,7 +21,7 @@ $ociSubcommands = @{ 'compute image export' = 'to-object to-object-uri' 'compute image import' = 'from-object from-object-uri' 'compute instance' = 'action attach-vnic detach-vnic get get-windows-initial-creds launch list list-vnics terminate update' - 'compute instance-console-connection' = 'create delete get list' + 'compute instance-console-connection' = 'create delete get get-plink-connection-string list' 'compute shape' = 'list' 'compute vnic-attachment' = 'get list' 'compute volume-attachment' = 'attach detach get list' @@ -46,6 +46,12 @@ $ociSubcommands = @{ 'dns record rrset' = 'delete get patch update' 'dns record zone' = 'get patch update' 'dns zone' = 'create delete get list update' + 'fs' = 'export export-set file-system mount-target snapshot' + 'fs export' = 'create delete get list' + 'fs export-set' = 'get list update' + 'fs file-system' = 'create delete get list update' + 'fs mount-target' = 'create delete get list update' + 'fs snapshot' = 'create delete get list' 'iam' = 'availability-domain compartment customer-secret-key dynamic-group group policy region region-subscription tag tag-namespace user' 'iam availability-domain' = 'list' 'iam compartment' = 'create get list update' @@ -61,7 +67,7 @@ $ociSubcommands = @{ 'iam user api-key' = 'delete list upload' 'iam user swift-password' = 'create delete list update' 'iam user ui-password' = 'create-or-reset' - 'lb' = 'backend backend-health backend-set backend-set-health certificate health-checker listener load-balancer load-balancer-health policy protocol shape work-request' + 'lb' = 'backend backend-health backend-set backend-set-health certificate health-checker listener load-balancer load-balancer-health path-route-set policy protocol shape work-request' 'lb backend' = 'create delete get list update' 'lb backend-health' = 'get' 'lb backend-set' = 'create delete get list update' @@ -71,6 +77,7 @@ $ociSubcommands = @{ 'lb listener' = 'create delete update' 'lb load-balancer' = 'create delete get list' 'lb load-balancer-health' = 'get list' + 'lb path-route-set' = 'create delete get list update' 'lb policy' = 'list' 'lb protocol' = 'list' 'lb shape' = 'list' @@ -156,6 +163,7 @@ $ociCommandsToLongParams = @{ 'compute instance-console-connection create' = 'defined-tags freeform-tags from-json help instance-id max-wait-seconds ssh-public-key-file wait-for-state wait-interval-seconds' 'compute instance-console-connection delete' = 'force from-json help if-match instance-console-connection-id max-wait-seconds wait-for-state wait-interval-seconds' 'compute instance-console-connection get' = 'from-json help instance-console-connection-id' + 'compute instance-console-connection get-plink-connection-string' = 'from-json help instance-console-connection-id local-vnc-port private-key-file ssh-proxy-port' 'compute instance-console-connection list' = 'all compartment-id from-json help instance-id limit page page-size' 'compute shape list' = 'all availability-domain compartment-id from-json help image-id limit page page-size' 'compute vnic-attachment get' = 'from-json help vnic-attachment-id' @@ -198,7 +206,7 @@ $ociCommandsToLongParams = @{ 'db patch-history list by-db-system' = 'all db-system-id from-json help limit page page-size' 'db system get' = 'db-system-id from-json help' 'db system launch' = 'admin-password availability-domain backup-subnet-id character-set cluster-name compartment-id cpu-core-count data-storage-percentage database-edition db-name db-version db-workload disk-redundancy display-name domain from-json help hostname initial-data-storage-size-in-gb license-model max-wait-seconds ncharacter-set node-count pdb-name shape ssh-authorized-keys-file subnet-id wait-for-state wait-interval-seconds' - 'db system list' = 'all compartment-id from-json help limit page page-size' + 'db system list' = 'all backup-id compartment-id from-json help limit page page-size' 'db system patch' = 'db-system-id from-json help patch-action patch-id' 'db system terminate' = 'db-system-id force from-json help if-match max-wait-seconds wait-for-state wait-interval-seconds' 'db system update' = 'cpu-core-count data-storage-size-in-gbs db-system-id force from-json help if-match max-wait-seconds patch-action patch-id ssh-authorized-keys-file wait-for-state wait-interval-seconds' @@ -220,6 +228,27 @@ $ociCommandsToLongParams = @{ 'dns zone get' = 'compartment-id from-json help if-modified-since if-none-match zone-name-or-id' 'dns zone list' = 'all compartment-id from-json help lifecycle-state limit name name-contains page page-size sort-by sort-order time-created-greater-than-or-equal-to time-created-less-than zone-type' 'dns zone update' = 'compartment-id external-masters force from-json help if-match if-unmodified-since max-wait-seconds wait-for-state wait-interval-seconds zone-name-or-id' + 'fs export create' = 'export-set-id file-system-id from-json help max-wait-seconds path wait-for-state wait-interval-seconds' + 'fs export delete' = 'export-id force from-json help if-match max-wait-seconds wait-for-state wait-interval-seconds' + 'fs export get' = 'export-id from-json help' + 'fs export list' = 'all compartment-id export-set-id file-system-id from-json help id lifecycle-state limit page page-size sort-by sort-order' + 'fs export-set get' = 'export-set-id from-json help' + 'fs export-set list' = 'all availability-domain compartment-id display-name from-json help id lifecycle-state limit page page-size sort-by sort-order' + 'fs export-set update' = 'display-name export-set-id from-json help if-match max-fs-stat-bytes max-fs-stat-files max-wait-seconds wait-for-state wait-interval-seconds' + 'fs file-system create' = 'availability-domain compartment-id display-name from-json help max-wait-seconds wait-for-state wait-interval-seconds' + 'fs file-system delete' = 'file-system-id force from-json help if-match max-wait-seconds wait-for-state wait-interval-seconds' + 'fs file-system get' = 'file-system-id from-json help' + 'fs file-system list' = 'all availability-domain compartment-id display-name from-json help id lifecycle-state limit page page-size sort-by sort-order' + 'fs file-system update' = 'display-name file-system-id from-json help if-match max-wait-seconds wait-for-state wait-interval-seconds' + 'fs mount-target create' = 'availability-domain compartment-id display-name from-json help hostname-label ip-address max-wait-seconds subnet-id wait-for-state wait-interval-seconds' + 'fs mount-target delete' = 'force from-json help if-match max-wait-seconds mount-target-id wait-for-state wait-interval-seconds' + 'fs mount-target get' = 'from-json help mount-target-id' + 'fs mount-target list' = 'all availability-domain compartment-id display-name export-set-id from-json help id lifecycle-state limit page page-size sort-by sort-order' + 'fs mount-target update' = 'display-name from-json help if-match max-wait-seconds mount-target-id wait-for-state wait-interval-seconds' + 'fs snapshot create' = 'file-system-id from-json help max-wait-seconds name wait-for-state wait-interval-seconds' + 'fs snapshot delete' = 'force from-json help if-match max-wait-seconds snapshot-id wait-for-state wait-interval-seconds' + 'fs snapshot get' = 'from-json help snapshot-id' + 'fs snapshot list' = 'all file-system-id from-json help id lifecycle-state limit page page-size sort-order' 'iam availability-domain list' = 'compartment-id from-json help' 'iam compartment create' = 'compartment-id defined-tags description freeform-tags from-json help max-wait-seconds name wait-for-state wait-interval-seconds' 'iam compartment get' = 'compartment-id from-json help' @@ -294,15 +323,20 @@ $ociCommandsToLongParams = @{ 'lb certificate list' = 'from-json help load-balancer-id' 'lb health-checker get' = 'backend-set-name from-json help load-balancer-id' 'lb health-checker update' = 'backend-set-name from-json help interval-in-millis load-balancer-id max-wait-seconds port protocol response-body-regex retries return-code timeout-in-millis url-path wait-for-state wait-interval-seconds' - 'lb listener create' = 'connection-configuration-idle-timeout default-backend-set-name from-json help load-balancer-id max-wait-seconds name port protocol ssl-certificate-name ssl-verify-depth ssl-verify-peer-certificate wait-for-state wait-interval-seconds' + 'lb listener create' = 'connection-configuration-idle-timeout default-backend-set-name from-json help load-balancer-id max-wait-seconds name path-route-set-name port protocol ssl-certificate-name ssl-verify-depth ssl-verify-peer-certificate wait-for-state wait-interval-seconds' 'lb listener delete' = 'force from-json help listener-name load-balancer-id max-wait-seconds wait-for-state wait-interval-seconds' - 'lb listener update' = 'connection-configuration-idle-timeout default-backend-set-name force from-json help listener-name load-balancer-id max-wait-seconds port protocol ssl-certificate-name ssl-verify-depth ssl-verify-peer-certificate wait-for-state wait-interval-seconds' - 'lb load-balancer create' = 'backend-sets certificates compartment-id display-name from-json help is-private listeners max-wait-seconds shape-name subnet-ids wait-for-state wait-interval-seconds' + 'lb listener update' = 'connection-configuration-idle-timeout default-backend-set-name force from-json help listener-name load-balancer-id max-wait-seconds path-route-set-name port protocol ssl-certificate-name ssl-verify-depth ssl-verify-peer-certificate wait-for-state wait-interval-seconds' + 'lb load-balancer create' = 'backend-sets certificates compartment-id display-name from-json help is-private listeners max-wait-seconds path-route-sets shape-name subnet-ids wait-for-state wait-interval-seconds' 'lb load-balancer delete' = 'force from-json help load-balancer-id max-wait-seconds wait-for-state wait-interval-seconds' 'lb load-balancer get' = 'from-json help load-balancer-id' 'lb load-balancer list' = 'all compartment-id detail display-name from-json help lifecycle-state limit page page-size sort-by sort-order' 'lb load-balancer-health get' = 'from-json help load-balancer-id' 'lb load-balancer-health list' = 'all compartment-id from-json help limit page page-size' + 'lb path-route-set create' = 'from-json help load-balancer-id max-wait-seconds name path-routes wait-for-state wait-interval-seconds' + 'lb path-route-set delete' = 'force from-json help load-balancer-id max-wait-seconds path-route-set-name wait-for-state wait-interval-seconds' + 'lb path-route-set get' = 'from-json help load-balancer-id path-route-set-name' + 'lb path-route-set list' = 'from-json help load-balancer-id' + 'lb path-route-set update' = 'force from-json help load-balancer-id max-wait-seconds path-route-set-name path-routes wait-for-state wait-interval-seconds' 'lb policy list' = 'all compartment-id from-json help limit page page-size' 'lb protocol list' = 'all compartment-id from-json help limit page page-size' 'lb shape list' = 'all compartment-id from-json help limit page page-size' @@ -379,11 +413,11 @@ $ociCommandsToLongParams = @{ 'network vnic get' = 'from-json help vnic-id' 'network vnic unassign-private-ip' = 'from-json help ip-address vnic-id' 'network vnic update' = 'display-name from-json help hostname-label if-match max-wait-seconds skip-source-dest-check vnic-id wait-for-state wait-interval-seconds' - 'os bucket create' = 'compartment-id from-json help metadata name namespace namespace-name public-access-type storage-tier' + 'os bucket create' = 'compartment-id defined-tags freeform-tags from-json help metadata name namespace namespace-name public-access-type storage-tier' 'os bucket delete' = 'bucket-name force from-json help if-match name namespace namespace-name' 'os bucket get' = 'bucket-name from-json help if-match if-none-match name namespace namespace-name' - 'os bucket list' = 'all compartment-id from-json help limit namespace namespace-name page page-size' - 'os bucket update' = 'bucket-name compartment-id from-json help if-match metadata name namespace namespace-name public-access-type' + 'os bucket list' = 'all compartment-id fields from-json help limit namespace namespace-name page page-size' + 'os bucket update' = 'bucket-name compartment-id defined-tags freeform-tags from-json help if-match metadata name namespace namespace-name public-access-type' 'os multipart abort' = 'bucket-name force from-json help namespace object-name upload-id' 'os multipart list' = 'all bucket-name from-json help limit namespace namespace-name page page-size' 'os ns get' = 'from-json help' @@ -398,7 +432,7 @@ $ociCommandsToLongParams = @{ 'os object list' = 'all bucket-name delimiter end fields from-json help limit namespace page-size prefix start' 'os object put' = 'bucket-name content-encoding content-language content-md5 content-type disable-parallel-uploads file force from-json help if-match metadata name namespace no-multipart parallel-upload-count part-size' 'os object rename' = 'bucket bucket-name from-json help name namespace namespace-name new-if-match new-if-none-match new-name new-obj-if-match-e-tag new-obj-if-none-match-e-tag source-name src-if-match src-obj-if-match-e-tag' - 'os object restore' = 'bucket from-json help name namespace' + 'os object restore' = 'bucket from-json help hours name namespace' 'os object restore-status' = 'bucket-name from-json help name namespace' 'os object resume-put' = 'bucket-name disable-parallel-uploads file from-json help name namespace parallel-upload-count part-size upload-id' 'os preauth-request create' = 'access-type bucket-name from-json help name namespace namespace-name object-name time-expires' @@ -469,6 +503,7 @@ $ociCommandsToShortParams = @{ 'compute instance-console-connection create' = '? h' 'compute instance-console-connection delete' = '? h' 'compute instance-console-connection get' = '? h' + 'compute instance-console-connection get-plink-connection-string' = '? h' 'compute instance-console-connection list' = '? c h' 'compute shape list' = '? c h' 'compute vnic-attachment get' = '? h' @@ -533,6 +568,27 @@ $ociCommandsToShortParams = @{ 'dns zone get' = '? c h' 'dns zone list' = '? c h' 'dns zone update' = '? c h' + 'fs export create' = '? h' + 'fs export delete' = '? h' + 'fs export get' = '? h' + 'fs export list' = '? c h' + 'fs export-set get' = '? h' + 'fs export-set list' = '? c h' + 'fs export-set update' = '? h' + 'fs file-system create' = '? c h' + 'fs file-system delete' = '? h' + 'fs file-system get' = '? h' + 'fs file-system list' = '? c h' + 'fs file-system update' = '? h' + 'fs mount-target create' = '? c h' + 'fs mount-target delete' = '? h' + 'fs mount-target get' = '? h' + 'fs mount-target list' = '? c h' + 'fs mount-target update' = '? h' + 'fs snapshot create' = '? h' + 'fs snapshot delete' = '? h' + 'fs snapshot get' = '? h' + 'fs snapshot list' = '? h' 'iam availability-domain list' = '? c h' 'iam compartment create' = '? c h' 'iam compartment get' = '? c h' @@ -616,6 +672,11 @@ $ociCommandsToShortParams = @{ 'lb load-balancer list' = '? c h' 'lb load-balancer-health get' = '? h' 'lb load-balancer-health list' = '? c h' + 'lb path-route-set create' = '? h' + 'lb path-route-set delete' = '? h' + 'lb path-route-set get' = '? h' + 'lb path-route-set list' = '? h' + 'lb path-route-set update' = '? h' 'lb policy list' = '? c h' 'lb protocol list' = '? c h' 'lb shape list' = '? c h' diff --git a/src/oci_cli/cli.py b/src/oci_cli/cli.py index f0b2263cd..88f8c1642 100644 --- a/src/oci_cli/cli.py +++ b/src/oci_cli/cli.py @@ -9,6 +9,7 @@ from .generated import compute_cli # noqa: F401 from .generated import database_cli # noqa: F401 from .generated import dns_cli # noqa: F401 +from .generated import filestorage_cli # noqa: F401 from .generated import identity_cli # noqa: F401 from .generated import loadbalancer_cli # noqa: F401 from .generated import objectstorage_cli # noqa: F401 @@ -18,6 +19,7 @@ from . import core_cli_extended # noqa: F401 from . import database_cli_extended # noqa: F401 from . import dns_cli_extended # noqa: F401 +from . import filestorage_cli_extended # noqa: F401 from . import identity_cli_extended # noqa: F401 from . import lb_cli_extended # noqa: F401 from . import final_command_processor # noqa: F401 diff --git a/src/oci_cli/cli_clients.py b/src/oci_cli/cli_clients.py index 68e23dd18..337c27f35 100644 --- a/src/oci_cli/cli_clients.py +++ b/src/oci_cli/cli_clients.py @@ -8,6 +8,7 @@ from oci.core import VirtualNetworkClient from oci.database import DatabaseClient from oci.dns import DnsClient +from oci.file_storage import FileStorageClient from oci.identity import IdentityClient from oci.load_balancer import LoadBalancerClient from oci.object_storage import ObjectStorageClient @@ -18,6 +19,7 @@ "compute": ComputeClient, "database": DatabaseClient, "dns": DnsClient, + "file_storage": FileStorageClient, "identity": IdentityClient, "load_balancer": LoadBalancerClient, "object_storage": ObjectStorageClient, @@ -29,6 +31,7 @@ "core": oci.core.models.core_type_mapping, "database": oci.database.models.database_type_mapping, "dns": oci.dns.models.dns_type_mapping, + "file_storage": oci.file_storage.models.file_storage_type_mapping, "identity": oci.identity.models.identity_type_mapping, "load_balancer": oci.load_balancer.models.load_balancer_type_mapping, "object_storage": oci.object_storage.models.object_storage_type_mapping diff --git a/src/oci_cli/cli_util.py b/src/oci_cli/cli_util.py index 085aa3435..a65ea182b 100644 --- a/src/oci_cli/cli_util.py +++ b/src/oci_cli/cli_util.py @@ -96,7 +96,9 @@ "virtual_network_group.help": "Networking Service", "get_console_history_content.command_name": "get-content", "instance_action.command_name": "action", - "volume_backup_group.command_name": "backup" + "volume_backup_group.command_name": "backup", + "file_storage_group.help": "File Storage Service", + "file_storage_group.command_name": "fs" } @@ -716,11 +718,11 @@ def serialize_key(private_key=None, public_key=None, passphrase=None): format=serialization.PublicFormat.SubjectPublicKeyInfo) -def copy_params_from_generated_command(generated_command, params_to_exclude): +def copy_params_from_generated_command(generated_command, params_to_exclude=[]): def copy_params(extended_func): index = 0 for param in generated_command.params[0:-2]: - if params_to_exclude and param.name not in params_to_exclude: + if params_to_exclude is not None and param.name not in params_to_exclude: extended_func.params.insert(index, param) index += 1 @@ -1181,7 +1183,7 @@ def _coalesce_param(ctx, param, value, required): # Decodes a byte string using stdout's encoding if we can get it, otherwise decode using the Python default def _try_decode_using_stdout(output): - if hasattr(sys.stdout, 'encoding'): + if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding is not None: return output.decode(sys.stdout.encoding) else: return output.decode(sys.getdefaultencoding()) diff --git a/src/oci_cli/core_cli_extended.py b/src/oci_cli/core_cli_extended.py index f9db84441..17d4754bd 100644 --- a/src/oci_cli/core_cli_extended.py +++ b/src/oci_cli/core_cli_extended.py @@ -5,6 +5,8 @@ from base64 import b64encode import click import json +import re +import six import sys from .generated import blockstorage_cli from .generated import compute_cli @@ -19,6 +21,10 @@ from . import retry_utils from .aliasing import CommandGroupWithAlias +INSTANCE_CONSOLE_CONNECTION_STRING_INTERMEDIATE_HOST_REGEX = "(instance-console\.[a-z0-9-]+\.(oraclecloud|oracleiaas)\.com)" +DEFAULT_LOCAL_VNC_PORT = 5900 +DEFAULT_SSH_PROXY_PORT = 5905 + blockstorage_cli.blockstorage_group.add_command(blockstorage_cli.volume_group) blockstorage_cli.blockstorage_group.add_command(blockstorage_cli.volume_backup_group) blockstorage_cli.blockstorage_group.add_command(blockstorage_cli.boot_volume_group) @@ -75,7 +81,7 @@ Note: user_data and ssh_authorized_keys can instead be specified using the parameters --user-data-file and --ssh-authorized-keys-file.""" compute_instance_launch_subnet_id_help = """The OCID of the subnet where the VNIC attached to this instance will be created.""" -compute_instance_launch_hostname_label_help = """The hostname for the VNIC that is created during instance launch. Used for DNS. The value is the hostname portion of the instance's fully qualified domain name (FQDN) (e.g., `bminstance-1` in FQDN `bminstance-1.subnet123.vcn1.oraclevcn.com`). Must be unique across all VNICs in the subnet and comply with [RFC 952] and [RFC 1123]. The value cannot be changed, and it can be retrieved from the [Vnic object]. +compute_instance_launch_hostname_label_help = """The hostname for the VNIC that is created during instance launch. Used for DNS. The value is the hostname portion of the instance's fully qualified domain name (FQDN) (e.g., `bminstance-1` in FQDN `bminstance-1.subnet123.vcn1.oraclevcn.com`). Must be unique across all VNICs in the subnet and comply with [RFC 952] and [RFC 1123]. The value cannot be changed, and it can be retrieved from the [Vnic]. For more information, see [DNS in Your Virtual Cloud Network].""" cli_util.update_param_help(compute_cli.launch_instance, 'metadata', compute_instance_launch_metadata_help, append=False, example=compute_instance_launch_metadata_example) @@ -83,7 +89,6 @@ cli_util.update_param_help(compute_cli.launch_instance, 'hostname_label', compute_instance_launch_hostname_label_help, example='`bminstance-1`') cli_util.update_param_help(compute_cli.launch_instance, 'source_details', """Use this parameter to specify whether a boot volume or an image should be used to launch a new instance.""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) cli_util.update_param_help(compute_cli.launch_instance, 'image_id', """The OCID of the image used to boot the instance. This is a shortcut for specifying an image source via the --source-details complex JSON parameter. If this parameter is provided, you cannot provide the --source-details or --source-boot-volume-id parameters.""", append=False) -cli_util.update_param_help(compute_cli.terminate_instance, 'preserve_boot_volume', """Defaults to true.""", append=True) image_source_details_example = """'{ "objectName": "image-to-import.qcow2", "bucketName": "MyBucket", "namespaceName": "MyNamespace", "sourceType": "objectStorageTuple" }' @@ -157,6 +162,12 @@ # update the type of the --skip-source-dest-check switch on update_vnic to be a boolean cli_util.get_param(virtualnetwork_cli.update_vnic, 'skip_source_dest_check').type = click.BOOL +# update help for instance console connections on windows +instance_console_connection_windows_help = """If you are attempting to start a VNC connection to an instance from a Windows machine without SSH installed, you can consider using plink instead. +The 'oci compute instance-console-connection get-plink-connection-string' command returns a PowerShell command which uses plink to launch the SSH tunnel necessary to start a VNC connection to the instance.""" +compute_cli.instance_console_connection_group.help = compute_cli.instance_console_connection_group.help + '\n\n' + instance_console_connection_windows_help +compute_cli.get_instance_console_connection.help = compute_cli.get_instance_console_connection.help + '\n\n' + instance_console_connection_windows_help + @compute_cli.image_group.command(cli_util.override('export_image_group.command_name', 'export'), cls=CommandGroupWithAlias, help="""Exports an image to the Oracle Cloud Infrastructure Object Storage Service. You can use the Object Storage Service URL, or the namespace, bucket name, and object name when specifying the location to export to. @@ -483,7 +494,7 @@ def launch_instance_extended(ctx, **kwargs): ctx.invoke(compute_cli.launch_instance, **kwargs) -@compute_cli.instance_group.command(name='attach-vnic', help="""Creates a secondary VNIC and attaches it to the specified instance. For more information about secondary VNICs, see [Managing Virtual Network Interface Cards (VNICs)].""") +@compute_cli.instance_group.command(name='attach-vnic', help="""Creates a secondary VNIC and attaches it to the specified instance. For more information about secondary VNICs, see [Virtual Network Interface Cards (VNICs)].""") @click.option('--instance-id', callback=cli_util.handle_required_param, help="""The OCID of the instance. [required]""") @click.option('--subnet-id', callback=cli_util.handle_required_param, help="""The OCID of the subnet to create the VNIC in. [required]""") @click.option('--vnic-display-name', callback=cli_util.handle_optional_param, help="""A user-friendly name for the VNIC. Does not have to be unique.""") @@ -572,6 +583,18 @@ def detach_vnic(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_ click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) wait_until(compute_client, retry_utils.call_funtion_with_default_retries(compute_client.get_vnic_attachment, vnic_attachment_id), 'lifecycle_state', wait_for_state, succeed_on_not_found=True, **wait_period_kwargs) + except 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 Exception 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) @@ -585,7 +608,7 @@ def detach_vnic(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_ @virtualnetwork_cli.vnic_group.command(name='assign-private-ip', help="""Assigns a secondary private IP address to the specified VNIC. The secondary private IP must be in the same subnet as the VNIC. This command can also be used to move an existing secondary private IP to the specified VNIC. -For more information about secondary private IPs, see [Managing IP Addresses] +For more information about secondary private IPs, see [IP Addresses] """) @click.option('--unassign-if-already-assigned', callback=cli_util.handle_optional_param, is_flag=True, default=False, help="""Force reassignment of the IP address if it's already assigned to another VNIC in the subnet. This is only relevant if an IP address is associated with this command.""") @click.pass_context @@ -665,7 +688,7 @@ def assign_private_ip(ctx, from_json, vnic_id, ip_address, display_name, hostnam This operation cannot be used with primary private IPs, which are automatically unassigned, and then deleted when the VNIC is terminated. -For more information about secondary private IPs, see [Managing IP Addresses] +For more information about secondary private IPs, see [IP Addresses] """) @click.option('--vnic-id', callback=cli_util.handle_required_param, help="""The OCID of the VNIC to unassign the private IP from. [required]""") @click.option('--ip-address', callback=cli_util.handle_required_param, help="""The secondary private IP to unassign from the VNIC. [required]""") @@ -735,7 +758,7 @@ def update_private_ip_extended(ctx, **kwargs): The default number of enabled serial console connections per tenancy is 10. -For more information about serial console access, see [Accessing the Serial Console].""") +For more information about serial console access, see [Accessing the Instance Console].""") @click.option('--ssh-public-key-file', callback=cli_util.handle_required_param, type=click.File('r'), help="""A file containing the SSH public key used to authenticate the serial console connection [required]""") @click.pass_context @json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'defined-tags': {'module': 'core', 'class': 'dict(str, dict(str, object))'}, 'freeform-tags': {'module': 'core', 'class': 'dict(str, string)'}}, output_type={'module': 'core', 'class': 'InstanceConsoleConnection'}) @@ -869,3 +892,57 @@ def get_public_ip_extended(ctx, **kwargs): command_args['ip_address'] = command_args.pop('public_ip_address') ctx.invoke(func_call_dict[func_call_key], **command_args) + + +@compute_cli.instance_console_connection_group.command(name='get-plink-connection-string', help="""Gets the plink command for starting an SSH tunnel on Windows which will allow VNC connections to the instance. Once you have started the tunnel, you can point your VNC client to localhost:{{--local-vnc-port}} to connect to the instance (default --local-vnc-port is {}).""".format(DEFAULT_LOCAL_VNC_PORT)) +@click.option('--instance-console-connection-id', callback=cli_util.handle_required_param, help="""The OCID of the intance console connection [required]""") +@click.option('--private-key-file', callback=cli_util.handle_required_param, help="""The path to the private key to be used for authentication. This is inserted into the generated connection string.""") +@click.option('--local-vnc-port', callback=cli_util.handle_optional_param, help="""This is the local port that you will point your VNC client at. This will be forwarded to the SSH tunnel created by executing the PowerShell command in the output. Default is {}.""".format(DEFAULT_LOCAL_VNC_PORT)) +@click.option('--ssh-proxy-port', callback=cli_util.handle_optional_param, help="""This is the local and remote port for the SSH tunnel. This may be any open port on your local machine. Default is {}.""".format(DEFAULT_SSH_PROXY_PORT)) +@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': 'core', 'class': 'InstanceConsoleConnection'}) +@cli_util.wrap_exceptions +def get_plink_connection_string(ctx, from_json, instance_console_connection_id, private_key_file, local_vnc_port, ssh_proxy_port): + if isinstance(instance_console_connection_id, six.string_types) and len(instance_console_connection_id.strip()) == 0: + raise click.UsageError('Parameter --instance-console-connection-id cannot be whitespace or empty string') + kwargs = {} + client = cli_util.build_client('compute', ctx) + result = client.get_instance_console_connection( + instance_console_connection_id=instance_console_connection_id, + **kwargs + ) + + instance_console_connection = result.data + + if local_vnc_port is None: + local_vnc_port = DEFAULT_LOCAL_VNC_PORT + + if ssh_proxy_port is None: + ssh_proxy_port = DEFAULT_SSH_PROXY_PORT + + # extract the intermediate host from the SSH connection string (this is the same regex used by the console) + m = re.search(INSTANCE_CONSOLE_CONNECTION_STRING_INTERMEDIATE_HOST_REGEX, instance_console_connection.connection_string) + intermediate_host = m.group(0) + + # There are two calls to plink + # plink -ssh -N -i {KEY} -P 443 -l {ICC_OCID} {ICC_HOST_SERVER} -L 5905:{INSTANCE_OCID}:5905 + # plink -L 5900:localhost:5900 localhost -P 5905 -N -i {KEY} -l {ICC_OCID} + connection_template = ( + 'Start-Job {{echo N | ' + 'plink -ssh -N -i "{private_key_file}" -P 443 -l {instance_console_connection_id} {intermediate_host} -L {ssh_proxy_port}:{instance_id}:{ssh_proxy_port}}}; sleep 5 ; ' + 'plink -L {local_vnc_port}:localhost:5900 localhost -P {ssh_proxy_port} -N -i "{private_key_file}" -l {instance_console_connection_id}' + ) + + connection_string = connection_template.format( + instance_id=instance_console_connection.instance_id, + instance_console_connection_id=instance_console_connection.id, + intermediate_host=intermediate_host, + private_key_file=private_key_file, + local_vnc_port=local_vnc_port, + ssh_proxy_port=ssh_proxy_port + ) + + # print directly to avoid escaping double quotes + click.echo(connection_string) diff --git a/src/oci_cli/filestorage_cli_extended.py b/src/oci_cli/filestorage_cli_extended.py new file mode 100644 index 000000000..c6b445500 --- /dev/null +++ b/src/oci_cli/filestorage_cli_extended.py @@ -0,0 +1,10 @@ +# coding: utf-8 +# Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + +from .generated import filestorage_cli + +filestorage_cli.file_storage_group.add_command(filestorage_cli.file_system_group) +filestorage_cli.file_storage_group.add_command(filestorage_cli.export_set_group) +filestorage_cli.file_storage_group.add_command(filestorage_cli.mount_target_group) +filestorage_cli.file_storage_group.add_command(filestorage_cli.export_group) +filestorage_cli.file_storage_group.add_command(filestorage_cli.snapshot_group) diff --git a/src/oci_cli/generated/__init__.py b/src/oci_cli/generated/__init__.py index ab8b5307d..959b3b136 100644 --- a/src/oci_cli/generated/__init__.py +++ b/src/oci_cli/generated/__init__.py @@ -1,2 +1,4 @@ # coding: utf-8 # Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + +# noqa: W391, W292 \ No newline at end of file diff --git a/src/oci_cli/generated/blockstorage_cli.py b/src/oci_cli/generated/blockstorage_cli.py index 2a59d72d8..07f491ca0 100644 --- a/src/oci_cli/generated/blockstorage_cli.py +++ b/src/oci_cli/generated/blockstorage_cli.py @@ -20,36 +20,25 @@ def blockstorage_group(): pass -@click.command(cli_util.override('volume_group.command_name', 'volume'), cls=CommandGroupWithAlias, help="""A detachable block volume device that allows you to dynamically expand -the storage capacity of an instance. For more information, see -[Overview of Cloud Volume Storage]. +@click.command(cli_util.override('volume_group.command_name', 'volume'), cls=CommandGroupWithAlias, help="""A detachable block volume device that allows you to dynamically expand the storage capacity of an instance. For more information, see [Overview of Cloud Volume Storage]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def volume_group(): pass -@click.command(cli_util.override('boot_volume_group.command_name', 'boot-volume'), cls=CommandGroupWithAlias, help="""A detachable boot volume device that contains the image used to boot an Compute instance. For more information, see -[Overview of Boot Volumes]. +@click.command(cli_util.override('boot_volume_group.command_name', 'boot-volume'), cls=CommandGroupWithAlias, help="""A detachable boot volume device that contains the image used to boot an Compute instance. For more information, see [Overview of Boot Volumes]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def boot_volume_group(): pass -@click.command(cli_util.override('volume_backup_group.command_name', 'volume-backup'), cls=CommandGroupWithAlias, help="""A point-in-time copy of a volume that can then be used to create a new block volume -or recover a block volume. For more information, see -[Overview of Cloud Volume Storage]. +@click.command(cli_util.override('volume_backup_group.command_name', 'volume-backup'), cls=CommandGroupWithAlias, help="""A point-in-time copy of a volume that can then be used to create a new block volume or recover a block volume. For more information, see [Overview of Cloud Volume Storage]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def volume_backup_group(): pass @@ -271,6 +260,18 @@ def delete_boot_volume(ctx, from_json, wait_for_state, max_wait_seconds, wait_in click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_boot_volume, boot_volume_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 Exception 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) @@ -314,6 +315,18 @@ def delete_volume(ctx, from_json, wait_for_state, max_wait_seconds, wait_interva click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_volume, volume_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 Exception 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) @@ -357,6 +370,18 @@ def delete_volume_backup(ctx, from_json, wait_for_state, max_wait_seconds, wait_ click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_volume_backup, volume_backup_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 Exception 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) diff --git a/src/oci_cli/generated/compute_cli.py b/src/oci_cli/generated/compute_cli.py index 196ca1373..ec13065ef 100644 --- a/src/oci_cli/generated/compute_cli.py +++ b/src/oci_cli/generated/compute_cli.py @@ -20,24 +20,17 @@ def compute_group(): pass -@click.command(cli_util.override('volume_group.command_name', 'volume'), cls=CommandGroupWithAlias, help="""A detachable block volume device that allows you to dynamically expand -the storage capacity of an instance. For more information, see -[Overview of Cloud Volume Storage]. +@click.command(cli_util.override('volume_group.command_name', 'volume'), cls=CommandGroupWithAlias, help="""A detachable block volume device that allows you to dynamically expand the storage capacity of an instance. For more information, see [Overview of Cloud Volume Storage]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def volume_group(): pass -@click.command(cli_util.override('image_group.command_name', 'image'), cls=CommandGroupWithAlias, help="""A boot disk image for launching an instance. For more information, see -[Overview of the Compute Service]. +@click.command(cli_util.override('image_group.command_name', 'image'), cls=CommandGroupWithAlias, help="""A boot disk image for launching an instance. For more information, see [Overview of the Compute Service]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def image_group(): pass @@ -49,50 +42,37 @@ def instance_credentials_group(): pass -@click.command(cli_util.override('instance_group.command_name', 'instance'), cls=CommandGroupWithAlias, help="""A compute host. The image used to launch the instance determines its operating system and other -software. The shape specified during the launch process determines the number of CPUs and memory -allocated to the instance. For more information, see -[Overview of the Compute Service]. +@click.command(cli_util.override('instance_group.command_name', 'instance'), cls=CommandGroupWithAlias, help="""A compute host. The image used to launch the instance determines its operating system and other software. The shape specified during the launch process determines the number of CPUs and memory allocated to the instance. For more information, see [Overview of the Compute Service]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def instance_group(): pass -@click.command(cli_util.override('boot_volume_group.command_name', 'boot-volume'), cls=CommandGroupWithAlias, help="""A detachable boot volume device that contains the image used to boot an Compute instance. For more information, see -[Overview of Boot Volumes]. +@click.command(cli_util.override('boot_volume_group.command_name', 'boot-volume'), cls=CommandGroupWithAlias, help="""A detachable boot volume device that contains the image used to boot an Compute instance. For more information, see [Overview of Boot Volumes]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def boot_volume_group(): pass -@click.command(cli_util.override('shape_group.command_name', 'shape'), cls=CommandGroupWithAlias, help="""A compute instance shape that can be used in [LaunchInstance]. -For more information, see [Overview of the Compute Service].""") +@click.command(cli_util.override('shape_group.command_name', 'shape'), cls=CommandGroupWithAlias, help="""A compute instance shape that can be used in [LaunchInstance]. For more information, see [Overview of the Compute Service].""") @cli_util.help_option_group def shape_group(): pass -@click.command(cli_util.override('vnic_attachment_group.command_name', 'vnic-attachment'), cls=CommandGroupWithAlias, help="""Represents an attachment between a VNIC and an instance. For more information, see -[Virtual Network Interface Cards (VNICs)].""") +@click.command(cli_util.override('vnic_attachment_group.command_name', 'vnic-attachment'), cls=CommandGroupWithAlias, help="""Represents an attachment between a VNIC and an instance. For more information, see [Virtual Network Interface Cards (VNICs)].""") @cli_util.help_option_group def vnic_attachment_group(): pass -@click.command(cli_util.override('volume_attachment_group.command_name', 'volume-attachment'), cls=CommandGroupWithAlias, help="""A base object for all types of attachments between a storage volume and an instance. -For specific details about iSCSI attachments, see -[IScsiVolumeAttachment Reference]. +@click.command(cli_util.override('volume_attachment_group.command_name', 'volume-attachment'), cls=CommandGroupWithAlias, help="""A base object for all types of attachments between a storage volume and an instance. For specific details about iSCSI attachments, see [IScsiVolumeAttachment Reference]. -For general information about volume attachments, see -[Overview of Block Volume Storage].""") +For general information about volume attachments, see [Overview of Block Volume Storage].""") @cli_util.help_option_group def volume_attachment_group(): pass @@ -104,19 +84,15 @@ def boot_volume_attachment_group(): pass -@click.command(cli_util.override('instance_console_connection_group.command_name', 'instance-console-connection'), cls=CommandGroupWithAlias, help="""The `InstanceConsoleConnection` API provides you with console access to virtual machine (VM) instances, -enabling you to troubleshoot malfunctioning instances remotely. +@click.command(cli_util.override('instance_console_connection_group.command_name', 'instance-console-connection'), cls=CommandGroupWithAlias, help="""The `InstanceConsoleConnection` API provides you with console access to virtual machine (VM) instances, enabling you to troubleshoot malfunctioning instances remotely. -For more information about console access, see -[Accessing the Console].""") +For more information about console access, see [Accessing the Console].""") @cli_util.help_option_group def instance_console_connection_group(): pass -@click.command(cli_util.override('console_history_group.command_name', 'console-history'), cls=CommandGroupWithAlias, help="""An instance's serial console data. It includes configuration messages that occur when the -instance boots, such as kernel and BIOS messages, and is useful for checking the status of -the instance or diagnosing problems. The console data is minimally formatted ASCII text.""") +@click.command(cli_util.override('console_history_group.command_name', 'console-history'), cls=CommandGroupWithAlias, help="""An instance's serial console data. It includes configuration messages that occur when the instance boots, such as kernel and BIOS messages, and is useful for checking the status of the instance or diagnosing problems. The console data is minimally formatted ASCII text.""") @cli_util.help_option_group def console_history_group(): pass @@ -505,6 +481,18 @@ def delete_console_history(ctx, from_json, wait_for_state, max_wait_seconds, wai click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_console_history, instance_console_history_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 Exception 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) @@ -548,6 +536,18 @@ def delete_image(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_image, image_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 Exception 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) @@ -591,6 +591,18 @@ def delete_instance_console_connection(ctx, from_json, wait_for_state, max_wait_ click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_instance_console_connection, instance_console_connection_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 Exception 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) @@ -636,6 +648,18 @@ def detach_boot_volume(ctx, from_json, wait_for_state, max_wait_seconds, wait_in click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_boot_volume_attachment, boot_volume_attachment_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 Exception 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) @@ -681,6 +705,18 @@ def detach_vnic(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_ click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_vnic_attachment, vnic_attachment_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 Exception 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) @@ -726,6 +762,18 @@ def detach_volume(ctx, from_json, wait_for_state, max_wait_seconds, wait_interva click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_volume_attachment, volume_attachment_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 Exception 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) @@ -1708,6 +1756,18 @@ def terminate_instance(ctx, from_json, wait_for_state, max_wait_seconds, wait_in click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_instance, instance_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 Exception 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) diff --git a/src/oci_cli/generated/database_cli.py b/src/oci_cli/generated/database_cli.py index befb3b750..98882e941 100644 --- a/src/oci_cli/generated/database_cli.py +++ b/src/oci_cli/generated/database_cli.py @@ -22,9 +22,7 @@ def db_group(): @click.command(cli_util.override('patch_group.command_name', 'patch'), cls=CommandGroupWithAlias, help="""A Patch for a DB System or DB Home. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, -see [Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def patch_group(): pass @@ -38,8 +36,7 @@ def db_version_group(): pass -@click.command(cli_util.override('backup_group.command_name', 'backup'), cls=CommandGroupWithAlias, help="""A database backup -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") +@click.command(cli_util.override('backup_group.command_name', 'backup'), cls=CommandGroupWithAlias, help="""A database backup To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def backup_group(): pass @@ -59,11 +56,7 @@ def patch_history_entry_group(): pass -@click.command(cli_util.override('db_system_shape_group.command_name', 'db-system-shape'), cls=CommandGroupWithAlias, help="""The shape of the DB System. The shape determines resources to allocate to the DB system - CPU cores and memory for VM shapes; CPU cores, memory and storage for non-VM (or bare metal) shapes. -For a description of shapes, see [DB System Launch Options]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. -If you're an administrator who needs to write policies to give users access, -see [Getting Started with Policies].""") +@click.command(cli_util.override('db_system_shape_group.command_name', 'db-system-shape'), cls=CommandGroupWithAlias, help="""The shape of the DB System. The shape determines resources to allocate to the DB system - CPU cores and memory for VM shapes; CPU cores, memory and storage for non-VM (or bare metal) shapes. For a description of shapes, see [DB System Launch Options]. To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def db_system_shape_group(): pass @@ -71,26 +64,17 @@ def db_system_shape_group(): @click.command(cli_util.override('data_guard_association_group.command_name', 'data-guard-association'), cls=CommandGroupWithAlias, help="""The properties that define a Data Guard association. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an -administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies]. +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies]. -For information about endpoints and signing API requests, see -[About the API]. For information about available SDKs and tools, see -[SDKS and Other Tools].""") +For information about endpoints and signing API requests, see [About the API]. For information about available SDKs and tools, see [SDKS and Other Tools].""") @cli_util.help_option_group def data_guard_association_group(): pass -@click.command(cli_util.override('db_home_group.command_name', 'db-home'), cls=CommandGroupWithAlias, help="""A directory where Oracle database software is installed. Each DB System can have multiple database homes, -and each database home can have multiple databases within it. All the databases within a single database home -must be the same database version, but different database homes can run different versions. For more information, -see [Managing Oracle Databases]. +@click.command(cli_util.override('db_home_group.command_name', 'db-home'), cls=CommandGroupWithAlias, help="""A directory where Oracle database software is installed. Each DB System can have multiple database homes, and each database home can have multiple databases within it. All the databases within a single database home must be the same database version, but different database homes can run different versions. For more information, see [Managing Oracle Databases]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an -administrator. If you're an administrator who needs to write policies to give users access, -see [Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def db_home_group(): pass @@ -98,19 +82,15 @@ def db_home_group(): @click.command(cli_util.override('db_system_group.command_name', 'db-system'), cls=CommandGroupWithAlias, help="""The Database Service supports several types of DB Systems, ranging in size, price, and performance. For details about each type of system, see: -- [Exadata DB Systems] -- [Bare Metal or VM DB Systems] +- [Exadata DB Systems] - [Bare Metal or VM DB Systems] To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies]. -For information about access control and compartments, see -[Overview of the Identity Service]. +For information about access control and compartments, see [Overview of the Identity Service]. -For information about Availability Domains, see -[Regions and Availability Domains]. +For information about Availability Domains, see [Regions and Availability Domains]. -To get a list of Availability Domains, use the `ListAvailabilityDomains` operation -in the Identity Service API.""") +To get a list of Availability Domains, use the `ListAvailabilityDomains` operation in the Identity Service API.""") @cli_util.help_option_group def db_system_group(): pass @@ -376,6 +356,18 @@ def delete_backup(ctx, from_json, wait_for_state, max_wait_seconds, wait_interva click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_backup, backup_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 Exception 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) @@ -422,6 +414,18 @@ def delete_db_home(ctx, from_json, wait_for_state, max_wait_seconds, wait_interv click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_db_home, db_home_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 Exception 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) @@ -1296,10 +1300,11 @@ def list_db_system_shapes(ctx, from_json, all_pages, page_size, availability_dom cli_util.render_response(result, ctx) -@db_system_group.command(name=cli_util.override('list_db_systems.command_name', 'list'), help="""Gets a list of the DB Systems in the specified compartment.""") +@db_system_group.command(name=cli_util.override('list_db_systems.command_name', 'list'), help="""Gets a list of the DB Systems in the specified compartment. You can specify a backupId to list only the DB Systems that support creating a database using this backup in this compartment.""") @click.option('--compartment-id', callback=cli_util.handle_required_param, help="""The compartment [OCID]. [required]""") @click.option('--limit', callback=cli_util.handle_optional_param, type=click.INT, help="""The maximum number of items to return.""") @click.option('--page', callback=cli_util.handle_optional_param, help="""The pagination token to continue listing from.""") +@click.option('--backup-id', callback=cli_util.handle_optional_param, help="""The OCID of the backup. Specify a backupId to list only the DB Systems that support creating a database using this backup in this compartment.""") @click.option('--all', 'all_pages', is_flag=True, callback=cli_util.handle_optional_param, help="""Fetches all pages of results. If you provide this option, then you cannot provide the --limit option.""") @click.option('--page-size', type=click.INT, callback=cli_util.handle_optional_param, 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({}) @@ -1307,7 +1312,7 @@ def list_db_system_shapes(ctx, from_json, all_pages, page_size, availability_dom @click.pass_context @json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}, output_type={'module': 'database', 'class': 'list[DbSystemSummary]'}) @cli_util.wrap_exceptions -def list_db_systems(ctx, from_json, all_pages, page_size, compartment_id, limit, page): +def list_db_systems(ctx, from_json, all_pages, page_size, compartment_id, limit, page, backup_id): if all_pages and limit: raise click.UsageError('If you provide the --all option you cannot provide the --limit option') @@ -1316,6 +1321,8 @@ def list_db_systems(ctx, from_json, all_pages, page_size, compartment_id, limit, kwargs['limit'] = limit if page is not None: kwargs['page'] = page + if backup_id is not None: + kwargs['backup_id'] = backup_id client = cli_util.build_client('database', ctx) if all_pages: if page_size: @@ -1535,6 +1542,18 @@ def terminate_db_system(ctx, from_json, wait_for_state, max_wait_seconds, wait_i click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_db_system, db_system_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 Exception 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) diff --git a/src/oci_cli/generated/dns_cli.py b/src/oci_cli/generated/dns_cli.py index 0c988d432..c700056e3 100644 --- a/src/oci_cli/generated/dns_cli.py +++ b/src/oci_cli/generated/dns_cli.py @@ -26,8 +26,7 @@ def zone_group(): pass -@click.command(cli_util.override('rr_set_group.command_name', 'rr-set'), cls=CommandGroupWithAlias, help="""A collection of DNS records of the same domain and type. For more -information about record types, see [Resource Record (RR) TYPEs].""") +@click.command(cli_util.override('rr_set_group.command_name', 'rr-set'), cls=CommandGroupWithAlias, help="""A collection of DNS records of the same domain and type. For more information about record types, see [Resource Record (RR) TYPEs].""") @cli_util.help_option_group def rr_set_group(): pass @@ -219,6 +218,18 @@ def delete_zone(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_ click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_zone, zone_name_or_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 Exception 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) diff --git a/src/oci_cli/generated/filestorage_cli.py b/src/oci_cli/generated/filestorage_cli.py new file mode 100644 index 000000000..89e7802bb --- /dev/null +++ b/src/oci_cli/generated/filestorage_cli.py @@ -0,0 +1,1124 @@ +# coding: utf-8 +# Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + +from __future__ import print_function +import click +import oci # noqa: F401 +import six # noqa: F401 +import sys # noqa: F401 +from ..cli_root import cli +from .. import cli_util +from .. import json_skeleton_utils +from .. import retry_utils # noqa: F401 +from .. import custom_types # noqa: F401 +from ..aliasing import CommandGroupWithAlias + + +@cli.command(cli_util.override('file_storage_group.command_name', 'file_storage'), cls=CommandGroupWithAlias, help=cli_util.override('file_storage_group.help', """The API for the File Storage Service. + +You can use the table of contents or the version selector and search tool to explore the File Storage Service API. +""")) +@cli_util.help_option_group +def file_storage_group(): + pass + + +@click.command(cli_util.override('file_system_group.command_name', 'file-system'), cls=CommandGroupWithAlias, help="""An NFS file system. To allow access to a file system, add it to an export set and associate the export set with a mount target. The same file system can be in multiple export sets and associated with multiple mount targets. + +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") +@cli_util.help_option_group +def file_system_group(): + pass + + +@click.command(cli_util.override('export_set_group.command_name', 'export-set'), cls=CommandGroupWithAlias, help="""A set of file systems to export through one or more mount targets. Composed of zero or more export resources.""") +@cli_util.help_option_group +def export_set_group(): + pass + + +@click.command(cli_util.override('mount_target_group.command_name', 'mount-target'), cls=CommandGroupWithAlias, help="""Provides access to a collection of file systems through one or more VNICs on a specified subnet. The set of file systems is controlled through the referenced export set.""") +@cli_util.help_option_group +def mount_target_group(): + pass + + +@click.command(cli_util.override('export_group.command_name', 'export'), cls=CommandGroupWithAlias, help="""A file system and the path that you can use to mount it. Each export resource belongs to exactly one export set. + +The export's path attribute is not a path in the referenced file system, but the value used by clients for the path component of the remotetarget argument when mounting the file system. + +The path must start with a slash (/) followed by a sequence of zero or more slash-separated path elements. For any two export resources associated with the same export set, except those in a 'DELETED' state, the path element sequence for the first export resource can't contain the complete path element sequence of the second export resource. + +For example, the following are acceptable: + + * /foo and /bar * /foo1 and /foo2 * /foo and /foo1 + +The following examples are not acceptable: * /foo and /foo/bar * / and /foo + +Paths may not end in a slash (/). No path element can be a period (.) or two periods in sequence (..). All path elements must be 255 bytes or less. + +No two non-'DELETED' export resources in the same export set can reference the same file system.""") +@cli_util.help_option_group +def export_group(): + pass + + +@click.command(cli_util.override('snapshot_group.command_name', 'snapshot'), cls=CommandGroupWithAlias, help="""A point-in-time snapshot of a specified file system.""") +@cli_util.help_option_group +def snapshot_group(): + pass + + +@export_group.command(name=cli_util.override('create_export.command_name', 'create'), help="""Creates a new export in the specified export set, path, and file system.""") +@click.option('--export-set-id', callback=cli_util.handle_required_param, help="""The OCID of this export's export set. [required]""") +@click.option('--file-system-id', callback=cli_util.handle_required_param, help="""The OCID of this export's file system. [required]""") +@click.option('--path', callback=cli_util.handle_required_param, help="""Path used to access the associated file system. + +Avoid entering confidential information. + +Example: `/mediafiles` [required]""") +@click.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED"]), callback=cli_util.handle_optional_param, 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.""") +@click.option('--max-wait-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@click.option('--wait-interval-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""Check every --wait-interval-seconds to see whether the resource to see if it 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': 'file_storage', 'class': 'Export'}) +@cli_util.wrap_exceptions +def create_export(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, export_set_id, file_system_id, path): + kwargs = {} + + details = {} + details['exportSetId'] = export_set_id + details['fileSystemId'] = file_system_id + details['path'] = path + + client = cli_util.build_client('file_storage', ctx) + result = client.create_export( + create_export_details=details, + **kwargs + ) + if wait_for_state: + if hasattr(client, 'get_export') and callable(getattr(client, 'get_export')): + try: + wait_period_kwargs = {} + if max_wait_seconds: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds: + 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, retry_utils.call_funtion_with_default_retries(client.get_export, result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + except Exception 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) + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@file_system_group.command(name=cli_util.override('create_file_system.command_name', 'create'), help="""Creates a new file system in the specified compartment and availability domain. Instances can mount file systems in another availability domain, but doing so might increase latency when compared to mounting instances in the same availability domain. + +After you create a file system, you can associate it with a mount target. Instances can then mount the file system by connecting to the mount target's IP address. You can associate a file system with more than one mount target at a time. + +For information about access control and compartments, see [Overview of the IAM Service]. + +For information about availability domains, see [Regions and Availability Domains]. To get a list of availability domains, use the `ListAvailabilityDomains` operation in the Identity and Access Management Service API. + +All Oracle Cloud Infrastructure resources, including file systems, get an Oracle-assigned, unique ID called an Oracle Cloud Identifier (OCID). When you create a resource, you can find its OCID in the response. You can also retrieve a resource's OCID by using a List API operation on that resource type or by viewing the resource in the Console.""") +@click.option('--availability-domain', callback=cli_util.handle_required_param, help="""The availability domain to create the file system in. + +Example: `Uocm:PHX-AD-1` [required]""") +@click.option('--compartment-id', callback=cli_util.handle_required_param, help="""The OCID of the compartment to create the file system in. [required]""") +@click.option('--display-name', callback=cli_util.handle_optional_param, help="""A user-friendly name. It does not have to be unique, and it is changeable. Avoid entering confidential information. + +Example: `My file system`""") +@click.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED"]), callback=cli_util.handle_optional_param, 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.""") +@click.option('--max-wait-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@click.option('--wait-interval-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""Check every --wait-interval-seconds to see whether the resource to see if it 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': 'file_storage', 'class': 'FileSystem'}) +@cli_util.wrap_exceptions +def create_file_system(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, availability_domain, compartment_id, display_name): + kwargs = {} + + details = {} + details['availabilityDomain'] = availability_domain + details['compartmentId'] = compartment_id + + if display_name is not None: + details['displayName'] = display_name + + client = cli_util.build_client('file_storage', ctx) + result = client.create_file_system( + create_file_system_details=details, + **kwargs + ) + if wait_for_state: + if hasattr(client, 'get_file_system') and callable(getattr(client, 'get_file_system')): + try: + wait_period_kwargs = {} + if max_wait_seconds: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds: + 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, retry_utils.call_funtion_with_default_retries(client.get_file_system, result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + except Exception 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) + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@mount_target_group.command(name=cli_util.override('create_mount_target.command_name', 'create'), help="""Creates a new mount target in the specified compartment and subnet. You can associate a file system with a mount target only when they exist in the same availability domain. Instances can connect to mount targets in another availablity domain, but you might see higher latency than with instances in the same availability domain as the mount target. + +Mount targets have one or more private IP addresses that you can provide as the host portion of remote target parameters in client mount commands. These private IP addresses are listed in the privateIpIds property of the mount target and are highly available. Mount targets also consume additional IP addresses in their subnet. + +For information about access control and compartments, see [Overview of the IAM Service]. + +For information about availability domains, see [Regions and Availability Domains]. To get a list of availability domains, use the `ListAvailabilityDomains` operation in the Identity and Access Management Service API. + +All Oracle Cloud Infrastructure Services resources, including mount targets, get an Oracle-assigned, unique ID called an Oracle Cloud Identifier (OCID). When you create a resource, you can find its OCID in the response. You can also retrieve a resource's OCID by using a List API operation on that resource type, or by viewing the resource in the Console.""") +@click.option('--availability-domain', callback=cli_util.handle_required_param, help="""The availability domain in which to create the mount target. + +Example: `Uocm:PHX-AD-1` [required]""") +@click.option('--compartment-id', callback=cli_util.handle_required_param, help="""The OCID of the compartment in which to create the mount target. [required]""") +@click.option('--subnet-id', callback=cli_util.handle_required_param, help="""The OCID of the subnet in which to create the mount target. [required]""") +@click.option('--display-name', callback=cli_util.handle_optional_param, help="""A user-friendly name. It does not have to be unique, and it is changeable. Avoid entering confidential information. + +Example: `My mount target`""") +@click.option('--hostname-label', callback=cli_util.handle_optional_param, help="""The hostname for the mount target's IP address, used for DNS resolution. The value is the hostname portion of the private IP address's fully qualified domain name (FQDN). For example, `files-1` in the FQDN `files-1.subnet123.vcn1.oraclevcn.com`. Must be unique across all VNICs in the subnet and comply with [RFC 952] and [RFC 1123]. + +For more information, see [DNS in Your Virtual Cloud Network]. + +Example: `files-1`""") +@click.option('--ip-address', callback=cli_util.handle_optional_param, help="""A private IP address of your choice. 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. + +Example: `10.0.3.3`""") +@click.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED"]), callback=cli_util.handle_optional_param, 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.""") +@click.option('--max-wait-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@click.option('--wait-interval-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""Check every --wait-interval-seconds to see whether the resource to see if it 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': 'file_storage', 'class': 'MountTarget'}) +@cli_util.wrap_exceptions +def create_mount_target(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, availability_domain, compartment_id, subnet_id, display_name, hostname_label, ip_address): + kwargs = {} + + details = {} + details['availabilityDomain'] = availability_domain + details['compartmentId'] = compartment_id + details['subnetId'] = subnet_id + + if display_name is not None: + details['displayName'] = display_name + + if hostname_label is not None: + details['hostnameLabel'] = hostname_label + + if ip_address is not None: + details['ipAddress'] = ip_address + + client = cli_util.build_client('file_storage', ctx) + result = client.create_mount_target( + create_mount_target_details=details, + **kwargs + ) + if wait_for_state: + if hasattr(client, 'get_mount_target') and callable(getattr(client, 'get_mount_target')): + try: + wait_period_kwargs = {} + if max_wait_seconds: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds: + 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, retry_utils.call_funtion_with_default_retries(client.get_mount_target, result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + except Exception 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) + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@snapshot_group.command(name=cli_util.override('create_snapshot.command_name', 'create'), help="""Creates a new snapshot of the specified file system. You can access the snapshot at `.snapshot/`.""") +@click.option('--file-system-id', callback=cli_util.handle_required_param, help="""The OCID of this export's file system. [required]""") +@click.option('--name', callback=cli_util.handle_required_param, help="""Name of the snapshot. This value is immutable. It must also be unique with respect to all other non-DELETED snapshots on the associated file system. + +Avoid entering confidential information. + +Example: `Sunday` [required]""") +@click.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED"]), callback=cli_util.handle_optional_param, 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.""") +@click.option('--max-wait-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@click.option('--wait-interval-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""Check every --wait-interval-seconds to see whether the resource to see if it 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': 'file_storage', 'class': 'Snapshot'}) +@cli_util.wrap_exceptions +def create_snapshot(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, file_system_id, name): + kwargs = {} + + details = {} + details['fileSystemId'] = file_system_id + details['name'] = name + + client = cli_util.build_client('file_storage', ctx) + result = client.create_snapshot( + create_snapshot_details=details, + **kwargs + ) + if wait_for_state: + if hasattr(client, 'get_snapshot') and callable(getattr(client, 'get_snapshot')): + try: + wait_period_kwargs = {} + if max_wait_seconds: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds: + 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, retry_utils.call_funtion_with_default_retries(client.get_snapshot, result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + except Exception 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) + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@export_group.command(name=cli_util.override('delete_export.command_name', 'delete'), help="""Deletes the specified export.""") +@click.option('--export-id', callback=cli_util.handle_required_param, help="""The OCID of the export. [required]""") +@click.option('--if-match', callback=cli_util.handle_optional_param, help="""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 +@click.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED"]), callback=cli_util.handle_optional_param, 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.""") +@click.option('--max-wait-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@click.option('--wait-interval-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""Check every --wait-interval-seconds to see whether the resource to see if it 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_export(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, export_id, if_match): + + if isinstance(export_id, six.string_types) and len(export_id.strip()) == 0: + raise click.UsageError('Parameter --export-id cannot be whitespace or empty string') + kwargs = {} + if if_match is not None: + kwargs['if_match'] = if_match + client = cli_util.build_client('file_storage', ctx) + result = client.delete_export( + export_id=export_id, + **kwargs + ) + if wait_for_state: + if hasattr(client, 'get_export') and callable(getattr(client, 'get_export')): + try: + wait_period_kwargs = {} + if max_wait_seconds: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds: + 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, retry_utils.call_funtion_with_default_retries(client.get_export, export_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 Exception 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) + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@file_system_group.command(name=cli_util.override('delete_file_system.command_name', 'delete'), help="""Deletes the specified file system. Before you delete the file system, verify that no remaining export resources still reference it. Deleting a file system also deletes all of its snapshots.""") +@click.option('--file-system-id', callback=cli_util.handle_required_param, help="""The OCID of the file system. [required]""") +@click.option('--if-match', callback=cli_util.handle_optional_param, help="""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 +@click.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED"]), callback=cli_util.handle_optional_param, 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.""") +@click.option('--max-wait-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@click.option('--wait-interval-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""Check every --wait-interval-seconds to see whether the resource to see if it 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_file_system(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, file_system_id, if_match): + + if isinstance(file_system_id, six.string_types) and len(file_system_id.strip()) == 0: + raise click.UsageError('Parameter --file-system-id cannot be whitespace or empty string') + kwargs = {} + if if_match is not None: + kwargs['if_match'] = if_match + client = cli_util.build_client('file_storage', ctx) + result = client.delete_file_system( + file_system_id=file_system_id, + **kwargs + ) + if wait_for_state: + if hasattr(client, 'get_file_system') and callable(getattr(client, 'get_file_system')): + try: + wait_period_kwargs = {} + if max_wait_seconds: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds: + 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, retry_utils.call_funtion_with_default_retries(client.get_file_system, file_system_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 Exception 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) + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@mount_target_group.command(name=cli_util.override('delete_mount_target.command_name', 'delete'), help="""Deletes the specified mount target. This operation also deletes the mount target's VNICs.""") +@click.option('--mount-target-id', callback=cli_util.handle_required_param, help="""The OCID of the mount target. [required]""") +@click.option('--if-match', callback=cli_util.handle_optional_param, help="""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 +@click.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED"]), callback=cli_util.handle_optional_param, 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.""") +@click.option('--max-wait-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@click.option('--wait-interval-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""Check every --wait-interval-seconds to see whether the resource to see if it 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_mount_target(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, mount_target_id, if_match): + + if isinstance(mount_target_id, six.string_types) and len(mount_target_id.strip()) == 0: + raise click.UsageError('Parameter --mount-target-id cannot be whitespace or empty string') + kwargs = {} + if if_match is not None: + kwargs['if_match'] = if_match + client = cli_util.build_client('file_storage', ctx) + result = client.delete_mount_target( + mount_target_id=mount_target_id, + **kwargs + ) + if wait_for_state: + if hasattr(client, 'get_mount_target') and callable(getattr(client, 'get_mount_target')): + try: + wait_period_kwargs = {} + if max_wait_seconds: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds: + 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, retry_utils.call_funtion_with_default_retries(client.get_mount_target, mount_target_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 Exception 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) + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@snapshot_group.command(name=cli_util.override('delete_snapshot.command_name', 'delete'), help="""Deletes the specified snapshot.""") +@click.option('--snapshot-id', callback=cli_util.handle_required_param, help="""The OCID of the snapshot. [required]""") +@click.option('--if-match', callback=cli_util.handle_optional_param, help="""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 +@click.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED"]), callback=cli_util.handle_optional_param, 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.""") +@click.option('--max-wait-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@click.option('--wait-interval-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""Check every --wait-interval-seconds to see whether the resource to see if it 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_snapshot(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, snapshot_id, if_match): + + if isinstance(snapshot_id, six.string_types) and len(snapshot_id.strip()) == 0: + raise click.UsageError('Parameter --snapshot-id cannot be whitespace or empty string') + kwargs = {} + if if_match is not None: + kwargs['if_match'] = if_match + client = cli_util.build_client('file_storage', ctx) + result = client.delete_snapshot( + snapshot_id=snapshot_id, + **kwargs + ) + if wait_for_state: + if hasattr(client, 'get_snapshot') and callable(getattr(client, 'get_snapshot')): + try: + wait_period_kwargs = {} + if max_wait_seconds: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds: + 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, retry_utils.call_funtion_with_default_retries(client.get_snapshot, snapshot_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 Exception 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) + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@export_group.command(name=cli_util.override('get_export.command_name', 'get'), help="""Gets the specified export's information.""") +@click.option('--export-id', callback=cli_util.handle_required_param, help="""The OCID of the export. [required]""") +@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': 'file_storage', 'class': 'Export'}) +@cli_util.wrap_exceptions +def get_export(ctx, from_json, export_id): + + if isinstance(export_id, six.string_types) and len(export_id.strip()) == 0: + raise click.UsageError('Parameter --export-id cannot be whitespace or empty string') + kwargs = {} + client = cli_util.build_client('file_storage', ctx) + result = client.get_export( + export_id=export_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@export_set_group.command(name=cli_util.override('get_export_set.command_name', 'get'), help="""Gets the specified export set's information.""") +@click.option('--export-set-id', callback=cli_util.handle_required_param, help="""The OCID of the export set. [required]""") +@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': 'file_storage', 'class': 'ExportSet'}) +@cli_util.wrap_exceptions +def get_export_set(ctx, from_json, export_set_id): + + if isinstance(export_set_id, six.string_types) and len(export_set_id.strip()) == 0: + raise click.UsageError('Parameter --export-set-id cannot be whitespace or empty string') + kwargs = {} + client = cli_util.build_client('file_storage', ctx) + result = client.get_export_set( + export_set_id=export_set_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@file_system_group.command(name=cli_util.override('get_file_system.command_name', 'get'), help="""Gets the specified file system's information.""") +@click.option('--file-system-id', callback=cli_util.handle_required_param, help="""The OCID of the file system. [required]""") +@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': 'file_storage', 'class': 'FileSystem'}) +@cli_util.wrap_exceptions +def get_file_system(ctx, from_json, file_system_id): + + if isinstance(file_system_id, six.string_types) and len(file_system_id.strip()) == 0: + raise click.UsageError('Parameter --file-system-id cannot be whitespace or empty string') + kwargs = {} + client = cli_util.build_client('file_storage', ctx) + result = client.get_file_system( + file_system_id=file_system_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@mount_target_group.command(name=cli_util.override('get_mount_target.command_name', 'get'), help="""Gets the specified mount target's information.""") +@click.option('--mount-target-id', callback=cli_util.handle_required_param, help="""The OCID of the mount target. [required]""") +@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': 'file_storage', 'class': 'MountTarget'}) +@cli_util.wrap_exceptions +def get_mount_target(ctx, from_json, mount_target_id): + + if isinstance(mount_target_id, six.string_types) and len(mount_target_id.strip()) == 0: + raise click.UsageError('Parameter --mount-target-id cannot be whitespace or empty string') + kwargs = {} + client = cli_util.build_client('file_storage', ctx) + result = client.get_mount_target( + mount_target_id=mount_target_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@snapshot_group.command(name=cli_util.override('get_snapshot.command_name', 'get'), help="""Gets the specified snapshot's information.""") +@click.option('--snapshot-id', callback=cli_util.handle_required_param, help="""The OCID of the snapshot. [required]""") +@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': 'file_storage', 'class': 'Snapshot'}) +@cli_util.wrap_exceptions +def get_snapshot(ctx, from_json, snapshot_id): + + if isinstance(snapshot_id, six.string_types) and len(snapshot_id.strip()) == 0: + raise click.UsageError('Parameter --snapshot-id cannot be whitespace or empty string') + kwargs = {} + client = cli_util.build_client('file_storage', ctx) + result = client.get_snapshot( + snapshot_id=snapshot_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@export_set_group.command(name=cli_util.override('list_export_sets.command_name', 'list'), help="""Lists the export set resources in the specified compartment.""") +@click.option('--compartment-id', callback=cli_util.handle_required_param, help="""The OCID of the compartment. [required]""") +@click.option('--availability-domain', callback=cli_util.handle_required_param, help="""The name of the availability domain. + +Example: `Uocm:PHX-AD-1` [required]""") +@click.option('--limit', callback=cli_util.handle_optional_param, type=click.INT, help="""The maximum number of items to return in a paginated \"List\" call. + +Example: `500`""") +@click.option('--page', callback=cli_util.handle_optional_param, help="""The value of the `opc-next-page` response header from the previous \"List\" call.""") +@click.option('--display-name', callback=cli_util.handle_optional_param, help="""A user-friendly name. It does not have to be unique, and it is changeable. + +Example: `My resource`""") +@click.option('--lifecycle-state', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED"]), help="""Filter results by the specified lifecycle state. Must be a valid state for the resource type.""") +@click.option('--id', callback=cli_util.handle_optional_param, help="""Filter results by OCID. Must be an OCID of the correct type for the resouce type.""") +@click.option('--sort-by', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["TIMECREATED", "DISPLAYNAME"]), help="""The field to sort by. You can provide either value, but not both. By default, when you sort by time created, results are shown in descending order. When you sort by display name, results are shown in ascending order.""") +@click.option('--sort-order', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["ASC", "DESC"]), help="""The sort order to use, either 'asc' or 'desc', where 'asc' is ascending and 'desc' is descending.""") +@click.option('--all', 'all_pages', is_flag=True, callback=cli_util.handle_optional_param, help="""Fetches all pages of results. If you provide this option, then you cannot provide the --limit option.""") +@click.option('--page-size', type=click.INT, callback=cli_util.handle_optional_param, 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': 'file_storage', 'class': 'list[ExportSetSummary]'}) +@cli_util.wrap_exceptions +def list_export_sets(ctx, from_json, all_pages, page_size, compartment_id, availability_domain, limit, page, display_name, lifecycle_state, id, sort_by, sort_order): + + if all_pages and limit: + raise click.UsageError('If you provide the --all option you cannot provide the --limit option') + if sort_by and not availability_domain and not all_pages: + raise click.UsageError('You must provide an --availability-domain when doing a --sort-by, unless you specify the --all parameter') + kwargs = {} + if limit is not None: + kwargs['limit'] = limit + if page is not None: + kwargs['page'] = page + if display_name is not None: + kwargs['display_name'] = display_name + if lifecycle_state is not None: + kwargs['lifecycle_state'] = lifecycle_state + if id is not None: + kwargs['id'] = id + if sort_by is not None: + kwargs['sort_by'] = sort_by + if sort_order is not None: + kwargs['sort_order'] = sort_order + client = cli_util.build_client('file_storage', ctx) + if all_pages: + if page_size: + kwargs['limit'] = page_size + + result = retry_utils.list_call_get_all_results_with_default_retries( + client.list_export_sets, + compartment_id=compartment_id, + availability_domain=availability_domain, + **kwargs + ) + elif limit is not None: + result = retry_utils.list_call_get_up_to_limit_with_default_retries( + client.list_export_sets, + limit, + page_size, + compartment_id=compartment_id, + availability_domain=availability_domain, + **kwargs + ) + else: + result = client.list_export_sets( + compartment_id=compartment_id, + availability_domain=availability_domain, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@export_group.command(name=cli_util.override('list_exports.command_name', 'list'), help="""Lists the export resources in the specified compartment. You must also specify an export set, a file system, or both.""") +@click.option('--compartment-id', callback=cli_util.handle_required_param, help="""The OCID of the compartment. [required]""") +@click.option('--limit', callback=cli_util.handle_optional_param, type=click.INT, help="""The maximum number of items to return in a paginated \"List\" call. + +Example: `500`""") +@click.option('--page', callback=cli_util.handle_optional_param, help="""The value of the `opc-next-page` response header from the previous \"List\" call.""") +@click.option('--export-set-id', callback=cli_util.handle_optional_param, help="""The OCID of the export set.""") +@click.option('--file-system-id', callback=cli_util.handle_optional_param, help="""The OCID of the file system.""") +@click.option('--lifecycle-state', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED"]), help="""Filter results by the specified lifecycle state. Must be a valid state for the resource type.""") +@click.option('--id', callback=cli_util.handle_optional_param, help="""Filter results by OCID. Must be an OCID of the correct type for the resouce type.""") +@click.option('--sort-by', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["TIMECREATED", "PATH"]), help="""The field to sort by. You can provide either value, but not both. By default, when you sort by time created, results are shown in descending order. When you sort by path, results are shown in ascending alphanumeric order.""") +@click.option('--sort-order', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["ASC", "DESC"]), help="""The sort order to use, either 'asc' or 'desc', where 'asc' is ascending and 'desc' is descending.""") +@click.option('--all', 'all_pages', is_flag=True, callback=cli_util.handle_optional_param, help="""Fetches all pages of results. If you provide this option, then you cannot provide the --limit option.""") +@click.option('--page-size', type=click.INT, callback=cli_util.handle_optional_param, 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': 'file_storage', 'class': 'list[ExportSummary]'}) +@cli_util.wrap_exceptions +def list_exports(ctx, from_json, all_pages, page_size, compartment_id, limit, page, export_set_id, file_system_id, lifecycle_state, id, sort_by, sort_order): + + 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 export_set_id is not None: + kwargs['export_set_id'] = export_set_id + if file_system_id is not None: + kwargs['file_system_id'] = file_system_id + if lifecycle_state is not None: + kwargs['lifecycle_state'] = lifecycle_state + if id is not None: + kwargs['id'] = id + if sort_by is not None: + kwargs['sort_by'] = sort_by + if sort_order is not None: + kwargs['sort_order'] = sort_order + client = cli_util.build_client('file_storage', ctx) + if all_pages: + if page_size: + kwargs['limit'] = page_size + + result = retry_utils.list_call_get_all_results_with_default_retries( + client.list_exports, + compartment_id=compartment_id, + **kwargs + ) + elif limit is not None: + result = retry_utils.list_call_get_up_to_limit_with_default_retries( + client.list_exports, + limit, + page_size, + compartment_id=compartment_id, + **kwargs + ) + else: + result = client.list_exports( + compartment_id=compartment_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@file_system_group.command(name=cli_util.override('list_file_systems.command_name', 'list'), help="""Lists the file system resources in the specified compartment.""") +@click.option('--compartment-id', callback=cli_util.handle_required_param, help="""The OCID of the compartment. [required]""") +@click.option('--availability-domain', callback=cli_util.handle_required_param, help="""The name of the availability domain. + +Example: `Uocm:PHX-AD-1` [required]""") +@click.option('--limit', callback=cli_util.handle_optional_param, type=click.INT, help="""The maximum number of items to return in a paginated \"List\" call. + +Example: `500`""") +@click.option('--page', callback=cli_util.handle_optional_param, help="""The value of the `opc-next-page` response header from the previous \"List\" call.""") +@click.option('--display-name', callback=cli_util.handle_optional_param, help="""A user-friendly name. It does not have to be unique, and it is changeable. + +Example: `My resource`""") +@click.option('--lifecycle-state', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED"]), help="""Filter results by the specified lifecycle state. Must be a valid state for the resource type.""") +@click.option('--id', callback=cli_util.handle_optional_param, help="""Filter results by OCID. Must be an OCID of the correct type for the resouce type.""") +@click.option('--sort-by', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["TIMECREATED", "DISPLAYNAME"]), help="""The field to sort by. You can provide either value, but not both. By default, when you sort by time created, results are shown in descending order. When you sort by display name, results are shown in ascending order.""") +@click.option('--sort-order', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["ASC", "DESC"]), help="""The sort order to use, either 'asc' or 'desc', where 'asc' is ascending and 'desc' is descending.""") +@click.option('--all', 'all_pages', is_flag=True, callback=cli_util.handle_optional_param, help="""Fetches all pages of results. If you provide this option, then you cannot provide the --limit option.""") +@click.option('--page-size', type=click.INT, callback=cli_util.handle_optional_param, 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': 'file_storage', 'class': 'list[FileSystemSummary]'}) +@cli_util.wrap_exceptions +def list_file_systems(ctx, from_json, all_pages, page_size, compartment_id, availability_domain, limit, page, display_name, lifecycle_state, id, sort_by, sort_order): + + if all_pages and limit: + raise click.UsageError('If you provide the --all option you cannot provide the --limit option') + if sort_by and not availability_domain and not all_pages: + raise click.UsageError('You must provide an --availability-domain when doing a --sort-by, unless you specify the --all parameter') + kwargs = {} + if limit is not None: + kwargs['limit'] = limit + if page is not None: + kwargs['page'] = page + if display_name is not None: + kwargs['display_name'] = display_name + if lifecycle_state is not None: + kwargs['lifecycle_state'] = lifecycle_state + if id is not None: + kwargs['id'] = id + if sort_by is not None: + kwargs['sort_by'] = sort_by + if sort_order is not None: + kwargs['sort_order'] = sort_order + client = cli_util.build_client('file_storage', ctx) + if all_pages: + if page_size: + kwargs['limit'] = page_size + + result = retry_utils.list_call_get_all_results_with_default_retries( + client.list_file_systems, + compartment_id=compartment_id, + availability_domain=availability_domain, + **kwargs + ) + elif limit is not None: + result = retry_utils.list_call_get_up_to_limit_with_default_retries( + client.list_file_systems, + limit, + page_size, + compartment_id=compartment_id, + availability_domain=availability_domain, + **kwargs + ) + else: + result = client.list_file_systems( + compartment_id=compartment_id, + availability_domain=availability_domain, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@mount_target_group.command(name=cli_util.override('list_mount_targets.command_name', 'list'), help="""Lists the mount target resources in the specified compartment.""") +@click.option('--compartment-id', callback=cli_util.handle_required_param, help="""The OCID of the compartment. [required]""") +@click.option('--availability-domain', callback=cli_util.handle_required_param, help="""The name of the availability domain. + +Example: `Uocm:PHX-AD-1` [required]""") +@click.option('--limit', callback=cli_util.handle_optional_param, type=click.INT, help="""The maximum number of items to return in a paginated \"List\" call. + +Example: `500`""") +@click.option('--page', callback=cli_util.handle_optional_param, help="""The value of the `opc-next-page` response header from the previous \"List\" call.""") +@click.option('--display-name', callback=cli_util.handle_optional_param, help="""A user-friendly name. It does not have to be unique, and it is changeable. + +Example: `My resource`""") +@click.option('--export-set-id', callback=cli_util.handle_optional_param, help="""The OCID of the export set.""") +@click.option('--lifecycle-state', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED"]), help="""Filter results by the specified lifecycle state. Must be a valid state for the resource type.""") +@click.option('--id', callback=cli_util.handle_optional_param, help="""Filter results by OCID. Must be an OCID of the correct type for the resouce type.""") +@click.option('--sort-by', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["TIMECREATED", "DISPLAYNAME"]), help="""The field to sort by. You can choose either value, but not both. By default, when you sort by time created, results are shown in descending order. When you sort by display name, results are shown in ascending order.""") +@click.option('--sort-order', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["ASC", "DESC"]), help="""The sort order to use, either 'asc' or 'desc', where 'asc' is ascending and 'desc' is descending.""") +@click.option('--all', 'all_pages', is_flag=True, callback=cli_util.handle_optional_param, help="""Fetches all pages of results. If you provide this option, then you cannot provide the --limit option.""") +@click.option('--page-size', type=click.INT, callback=cli_util.handle_optional_param, 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': 'file_storage', 'class': 'list[MountTargetSummary]'}) +@cli_util.wrap_exceptions +def list_mount_targets(ctx, from_json, all_pages, page_size, compartment_id, availability_domain, limit, page, display_name, export_set_id, lifecycle_state, id, sort_by, sort_order): + + if all_pages and limit: + raise click.UsageError('If you provide the --all option you cannot provide the --limit option') + if sort_by and not availability_domain and not all_pages: + raise click.UsageError('You must provide an --availability-domain when doing a --sort-by, unless you specify the --all parameter') + kwargs = {} + if limit is not None: + kwargs['limit'] = limit + if page is not None: + kwargs['page'] = page + if display_name is not None: + kwargs['display_name'] = display_name + if export_set_id is not None: + kwargs['export_set_id'] = export_set_id + if lifecycle_state is not None: + kwargs['lifecycle_state'] = lifecycle_state + if id is not None: + kwargs['id'] = id + if sort_by is not None: + kwargs['sort_by'] = sort_by + if sort_order is not None: + kwargs['sort_order'] = sort_order + client = cli_util.build_client('file_storage', ctx) + if all_pages: + if page_size: + kwargs['limit'] = page_size + + result = retry_utils.list_call_get_all_results_with_default_retries( + client.list_mount_targets, + compartment_id=compartment_id, + availability_domain=availability_domain, + **kwargs + ) + elif limit is not None: + result = retry_utils.list_call_get_up_to_limit_with_default_retries( + client.list_mount_targets, + limit, + page_size, + compartment_id=compartment_id, + availability_domain=availability_domain, + **kwargs + ) + else: + result = client.list_mount_targets( + compartment_id=compartment_id, + availability_domain=availability_domain, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@snapshot_group.command(name=cli_util.override('list_snapshots.command_name', 'list'), help="""Lists snapshots of the specified file system.""") +@click.option('--file-system-id', callback=cli_util.handle_required_param, help="""The OCID of the file system. [required]""") +@click.option('--limit', callback=cli_util.handle_optional_param, type=click.INT, help="""The maximum number of items to return in a paginated \"List\" call. + +Example: `500`""") +@click.option('--page', callback=cli_util.handle_optional_param, help="""The value of the `opc-next-page` response header from the previous \"List\" call.""") +@click.option('--lifecycle-state', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED"]), help="""Filter results by the specified lifecycle state. Must be a valid state for the resource type.""") +@click.option('--id', callback=cli_util.handle_optional_param, help="""Filter results by OCID. Must be an OCID of the correct type for the resouce type.""") +@click.option('--sort-order', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["ASC", "DESC"]), help="""The sort order to use, either 'asc' or 'desc', where 'asc' is ascending and 'desc' is descending.""") +@click.option('--all', 'all_pages', is_flag=True, callback=cli_util.handle_optional_param, help="""Fetches all pages of results. If you provide this option, then you cannot provide the --limit option.""") +@click.option('--page-size', type=click.INT, callback=cli_util.handle_optional_param, 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': 'file_storage', 'class': 'list[SnapshotSummary]'}) +@cli_util.wrap_exceptions +def list_snapshots(ctx, from_json, all_pages, page_size, file_system_id, limit, page, lifecycle_state, id, sort_order): + + 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 lifecycle_state is not None: + kwargs['lifecycle_state'] = lifecycle_state + if id is not None: + kwargs['id'] = id + if sort_order is not None: + kwargs['sort_order'] = sort_order + client = cli_util.build_client('file_storage', ctx) + if all_pages: + if page_size: + kwargs['limit'] = page_size + + result = retry_utils.list_call_get_all_results_with_default_retries( + client.list_snapshots, + file_system_id=file_system_id, + **kwargs + ) + elif limit is not None: + result = retry_utils.list_call_get_up_to_limit_with_default_retries( + client.list_snapshots, + limit, + page_size, + file_system_id=file_system_id, + **kwargs + ) + else: + result = client.list_snapshots( + file_system_id=file_system_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + +@export_set_group.command(name=cli_util.override('update_export_set.command_name', 'update'), help="""Updates the specified export set's information.""") +@click.option('--export-set-id', callback=cli_util.handle_required_param, help="""The OCID of the export set. [required]""") +@click.option('--display-name', callback=cli_util.handle_optional_param, help="""A user-friendly name. It does not have to be unique, and it is changeable. Avoid entering confidential information. + +Example: `My export set`""") +@click.option('--max-fs-stat-bytes', callback=cli_util.handle_optional_param, type=click.INT, help="""Controls the maximum `tbytes`, `fbytes`, and `abytes` values reported by `NFS FSSTAT` calls through any associated mount targets. This is an advanced feature. For most applications, use the default value. The `tbytes` value reported by `FSSTAT` will be `maxFsStatBytes`. The value of `fbytes` and `abytes` will be `maxFsStatBytes` minus the metered size of the file system. If the metered size is larger than `maxFsStatBytes`, then `fbytes` and `abytes` will both be '0'.""") +@click.option('--max-fs-stat-files', callback=cli_util.handle_optional_param, type=click.INT, help="""Controls the maximum `ffiles`, `ffiles`, and `afiles` values reported by `NFS FSSTAT` calls through any associated mount targets. This is an advanced feature. For most applications, use the default value. The `tfiles` value reported by `FSSTAT` will be `maxFsStatFiles`. The value of `ffiles` and `afiles` will be `maxFsStatFiles` minus the metered size of the file system. If the metered size is larger than `maxFsStatFiles`, then `ffiles` and `afiles` will both be '0'.""") +@click.option('--if-match', callback=cli_util.handle_optional_param, help="""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.""") +@click.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED"]), callback=cli_util.handle_optional_param, 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.""") +@click.option('--max-wait-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@click.option('--wait-interval-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""Check every --wait-interval-seconds to see whether the resource to see if it 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': 'file_storage', 'class': 'ExportSet'}) +@cli_util.wrap_exceptions +def update_export_set(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, export_set_id, display_name, max_fs_stat_bytes, max_fs_stat_files, if_match): + + if isinstance(export_set_id, six.string_types) and len(export_set_id.strip()) == 0: + raise click.UsageError('Parameter --export-set-id cannot be whitespace or empty string') + kwargs = {} + if if_match is not None: + kwargs['if_match'] = if_match + + details = {} + + if display_name is not None: + details['displayName'] = display_name + + if max_fs_stat_bytes is not None: + details['maxFsStatBytes'] = max_fs_stat_bytes + + if max_fs_stat_files is not None: + details['maxFsStatFiles'] = max_fs_stat_files + + client = cli_util.build_client('file_storage', ctx) + result = client.update_export_set( + export_set_id=export_set_id, + update_export_set_details=details, + **kwargs + ) + if wait_for_state: + if hasattr(client, 'get_export_set') and callable(getattr(client, 'get_export_set')): + try: + wait_period_kwargs = {} + if max_wait_seconds: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds: + 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, retry_utils.call_funtion_with_default_retries(client.get_export_set, result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + except Exception 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) + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@file_system_group.command(name=cli_util.override('update_file_system.command_name', 'update'), help="""Updates the specified file system's information. You can use this operation to rename a file system.""") +@click.option('--file-system-id', callback=cli_util.handle_required_param, help="""The OCID of the file system. [required]""") +@click.option('--display-name', callback=cli_util.handle_optional_param, help="""A user-friendly name. It does not have to be unique, and it is changeable. Avoid entering confidential information. + +Example: `My file system`""") +@click.option('--if-match', callback=cli_util.handle_optional_param, help="""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.""") +@click.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED"]), callback=cli_util.handle_optional_param, 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.""") +@click.option('--max-wait-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@click.option('--wait-interval-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""Check every --wait-interval-seconds to see whether the resource to see if it 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': 'file_storage', 'class': 'FileSystem'}) +@cli_util.wrap_exceptions +def update_file_system(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, file_system_id, display_name, if_match): + + if isinstance(file_system_id, six.string_types) and len(file_system_id.strip()) == 0: + raise click.UsageError('Parameter --file-system-id cannot be whitespace or empty string') + kwargs = {} + if if_match is not None: + kwargs['if_match'] = if_match + + details = {} + + if display_name is not None: + details['displayName'] = display_name + + client = cli_util.build_client('file_storage', ctx) + result = client.update_file_system( + file_system_id=file_system_id, + update_file_system_details=details, + **kwargs + ) + if wait_for_state: + if hasattr(client, 'get_file_system') and callable(getattr(client, 'get_file_system')): + try: + wait_period_kwargs = {} + if max_wait_seconds: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds: + 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, retry_utils.call_funtion_with_default_retries(client.get_file_system, result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + except Exception 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) + else: + click.echo('Unable to wait for the resource to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + +@mount_target_group.command(name=cli_util.override('update_mount_target.command_name', 'update'), help="""Updates the specified mount target's information.""") +@click.option('--mount-target-id', callback=cli_util.handle_required_param, help="""The OCID of the mount target. [required]""") +@click.option('--display-name', callback=cli_util.handle_optional_param, help="""A user-friendly name. Does not have to be unique, and it is changeable. Avoid entering confidential information. + +Example: `My mount target`""") +@click.option('--if-match', callback=cli_util.handle_optional_param, help="""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.""") +@click.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["CREATING", "ACTIVE", "DELETING", "DELETED", "FAILED"]), callback=cli_util.handle_optional_param, 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.""") +@click.option('--max-wait-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""The maximum time to wait for the resource to reach the lifecycle state defined by --wait-for-state. Defaults to 1200 seconds.""") +@click.option('--wait-interval-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""Check every --wait-interval-seconds to see whether the resource to see if it 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': 'file_storage', 'class': 'MountTarget'}) +@cli_util.wrap_exceptions +def update_mount_target(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, mount_target_id, display_name, if_match): + + if isinstance(mount_target_id, six.string_types) and len(mount_target_id.strip()) == 0: + raise click.UsageError('Parameter --mount-target-id cannot be whitespace or empty string') + kwargs = {} + if if_match is not None: + kwargs['if_match'] = if_match + + details = {} + + if display_name is not None: + details['displayName'] = display_name + + client = cli_util.build_client('file_storage', ctx) + result = client.update_mount_target( + mount_target_id=mount_target_id, + update_mount_target_details=details, + **kwargs + ) + if wait_for_state: + if hasattr(client, 'get_mount_target') and callable(getattr(client, 'get_mount_target')): + try: + wait_period_kwargs = {} + if max_wait_seconds: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds: + 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, retry_utils.call_funtion_with_default_retries(client.get_mount_target, result.data.id), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + except Exception 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) + 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/src/oci_cli/generated/identity_cli.py b/src/oci_cli/generated/identity_cli.py index fb459a1de..73d2fafe6 100644 --- a/src/oci_cli/generated/identity_cli.py +++ b/src/oci_cli/generated/identity_cli.py @@ -20,24 +20,19 @@ def identity_group(): pass -@click.command(cli_util.override('tag_namespace_group.command_name', 'tag-namespace'), cls=CommandGroupWithAlias, help="""A managed container for defined tags. A tag namespace is unique in a tenancy. A tag namespace can't be deleted. -For more information, see [Managing Tags and Tag Namespaces].""") +@click.command(cli_util.override('tag_namespace_group.command_name', 'tag-namespace'), cls=CommandGroupWithAlias, help="""A managed container for defined tags. A tag namespace is unique in a tenancy. A tag namespace can't be deleted. For more information, see [Managing Tags and Tag Namespaces].""") @cli_util.help_option_group def tag_namespace_group(): pass -@click.command(cli_util.override('availability_domain_group.command_name', 'availability-domain'), cls=CommandGroupWithAlias, help="""One or more isolated, fault-tolerant Oracle data centers that host cloud resources such as instances, volumes, -and subnets. A region contains several Availability Domains. For more information, see -[Regions and Availability Domains].""") +@click.command(cli_util.override('availability_domain_group.command_name', 'availability-domain'), cls=CommandGroupWithAlias, help="""One or more isolated, fault-tolerant Oracle data centers that host cloud resources such as instances, volumes, and subnets. A region contains several Availability Domains. For more information, see [Regions and Availability Domains].""") @cli_util.help_option_group def availability_domain_group(): pass -@click.command(cli_util.override('customer_secret_key_group.command_name', 'customer-secret-key'), cls=CommandGroupWithAlias, help="""A `CustomerSecretKey` is an Oracle-provided key for using the Object Storage Service's -[Amazon S3 compatible API]. -A user can have up to two secret keys at a time. +@click.command(cli_util.override('customer_secret_key_group.command_name', 'customer-secret-key'), cls=CommandGroupWithAlias, help="""A `CustomerSecretKey` is an Oracle-provided key for using the Object Storage Service's [Amazon S3 compatible API]. A user can have up to two secret keys at a time. **Note:** The secret key is always an Oracle-generated string; you can't change it to a string of your choice. @@ -47,58 +42,39 @@ def customer_secret_key_group(): pass -@click.command(cli_util.override('idp_group_mapping_group.command_name', 'idp-group-mapping'), cls=CommandGroupWithAlias, help="""A mapping between a single group defined by the identity provider (IdP) you're federating with -and a single IAM Service [group] in Oracle Cloud Infrastructure. -For more information about group mappings and what they're for, see -[Identity Providers and Federation]. +@click.command(cli_util.override('idp_group_mapping_group.command_name', 'idp-group-mapping'), cls=CommandGroupWithAlias, help="""A mapping between a single group defined by the identity provider (IdP) you're federating with and a single IAM Service [group] in Oracle Cloud Infrastructure. For more information about group mappings and what they're for, see [Identity Providers and Federation]. -A given IdP group can be mapped to zero, one, or multiple IAM Service groups, and vice versa. -But each `IdPGroupMapping` object is between only a single IdP group and IAM Service group. -Each `IdPGroupMapping` object has its own OCID. +A given IdP group can be mapped to zero, one, or multiple IAM Service groups, and vice versa. But each `IdPGroupMapping` object is between only a single IdP group and IAM Service group. Each `IdPGroupMapping` object has its own OCID. -**Note:** Any users who are in more than 50 IdP groups cannot be authenticated to use the Oracle -Cloud Infrastructure Console.""") +**Note:** Any users who are in more than 50 IdP groups cannot be authenticated to use the Oracle Cloud Infrastructure Console.""") @cli_util.help_option_group def idp_group_mapping_group(): pass -@click.command(cli_util.override('tenancy_group.command_name', 'tenancy'), cls=CommandGroupWithAlias, help="""The root compartment that contains all of your organization's compartments and other -Oracle Cloud Infrastructure cloud resources. When you sign up for Oracle Cloud Infrastructure, -Oracle creates a tenancy for your company, which is a secure and isolated partition -where you can create, organize, and administer your cloud resources. +@click.command(cli_util.override('tenancy_group.command_name', 'tenancy'), cls=CommandGroupWithAlias, help="""The root compartment that contains all of your organization's compartments and other Oracle Cloud Infrastructure cloud resources. When you sign up for Oracle Cloud Infrastructure, Oracle creates a tenancy for your company, which is a secure and isolated partition where you can create, organize, and administer your cloud resources. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, -see [Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def tenancy_group(): pass -@click.command(cli_util.override('user_group_membership_group.command_name', 'user-group-membership'), cls=CommandGroupWithAlias, help="""An object that represents the membership of a user in a group. When you add a user to a group, the result is a -`UserGroupMembership` with its own OCID. To remove a user from a group, you delete the `UserGroupMembership` object.""") +@click.command(cli_util.override('user_group_membership_group.command_name', 'user-group-membership'), cls=CommandGroupWithAlias, help="""An object that represents the membership of a user in a group. When you add a user to a group, the result is a `UserGroupMembership` with its own OCID. To remove a user from a group, you delete the `UserGroupMembership` object.""") @cli_util.help_option_group def user_group_membership_group(): pass -@click.command(cli_util.override('identity_provider_group.command_name', 'identity-provider'), cls=CommandGroupWithAlias, help="""The resulting base object when you add an identity provider to your tenancy. A -[Saml2IdentityProvider] -is a specific type of `IdentityProvider` that supports the SAML 2.0 protocol. Each -`IdentityProvider` object has its own OCID. For more information, see -[Identity Providers and Federation]. +@click.command(cli_util.override('identity_provider_group.command_name', 'identity-provider'), cls=CommandGroupWithAlias, help="""The resulting base object when you add an identity provider to your tenancy. A [Saml2IdentityProvider] is a specific type of `IdentityProvider` that supports the SAML 2.0 protocol. Each `IdentityProvider` object has its own OCID. For more information, see [Identity Providers and Federation]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, -see [Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def identity_provider_group(): pass -@click.command(cli_util.override('ui_password_group.command_name', 'ui-password'), cls=CommandGroupWithAlias, help="""A text password that enables a user to sign in to the Console, the user interface for interacting with Oracle -Cloud Infrastructure. +@click.command(cli_util.override('ui_password_group.command_name', 'ui-password'), cls=CommandGroupWithAlias, help="""A text password that enables a user to sign in to the Console, the user interface for interacting with Oracle Cloud Infrastructure. For more information about user credentials, see [User Credentials].""") @cli_util.help_option_group @@ -106,10 +82,7 @@ def ui_password_group(): pass -@click.command(cli_util.override('api_key_group.command_name', 'api-key'), cls=CommandGroupWithAlias, help="""A PEM-format RSA credential for securing requests to the Oracle Cloud Infrastructure REST API. Also known -as an *API signing key*. Specifically, this is the public key from the key pair. The private key remains with -the user calling the API. For information about generating a key pair -in the required PEM format, see [Required Keys and OCIDs]. +@click.command(cli_util.override('api_key_group.command_name', 'api-key'), cls=CommandGroupWithAlias, help="""A PEM-format RSA credential for securing requests to the Oracle Cloud Infrastructure REST API. Also known as an *API signing key*. Specifically, this is the public key from the key pair. The private key remains with the user calling the API. For information about generating a key pair in the required PEM format, see [Required Keys and OCIDs]. **Important:** This is **not** the SSH key for accessing compute instances. @@ -121,74 +94,47 @@ def api_key_group(): pass -@click.command(cli_util.override('region_subscription_group.command_name', 'region-subscription'), cls=CommandGroupWithAlias, help="""An object that represents your tenancy's access to a particular region (i.e., a subscription), the status of that -access, and whether that region is the home region. For more information, see [Managing Regions]. +@click.command(cli_util.override('region_subscription_group.command_name', 'region-subscription'), cls=CommandGroupWithAlias, help="""An object that represents your tenancy's access to a particular region (i.e., a subscription), the status of that access, and whether that region is the home region. For more information, see [Managing Regions]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, -see [Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def region_subscription_group(): pass -@click.command(cli_util.override('compartment_group.command_name', 'compartment'), cls=CommandGroupWithAlias, help="""A collection of related resources. Compartments are a fundamental component of Oracle Cloud Infrastructure -for organizing and isolating your cloud resources. You use them to clearly separate resources for the purposes -of measuring usage and billing, access (through the use of IAM Service policies), and isolation (separating the -resources for one project or business unit from another). A common approach is to create a compartment for each -major part of your organization. For more information, see -[Overview of the IAM Service] and also -[Setting Up Your Tenancy]. +@click.command(cli_util.override('compartment_group.command_name', 'compartment'), cls=CommandGroupWithAlias, help="""A collection of related resources. Compartments are a fundamental component of Oracle Cloud Infrastructure for organizing and isolating your cloud resources. You use them to clearly separate resources for the purposes of measuring usage and billing, access (through the use of IAM Service policies), and isolation (separating the resources for one project or business unit from another). A common approach is to create a compartment for each major part of your organization. For more information, see [Overview of the IAM Service] and also [Setting Up Your Tenancy]. -To place a resource in a compartment, simply specify the compartment ID in the "Create" request object when -initially creating the resource. For example, to launch an instance into a particular compartment, specify -that compartment's OCID in the `LaunchInstance` request. You can't move an existing resource from one -compartment to another. +To place a resource in a compartment, simply specify the compartment ID in the \"Create\" request object when initially creating the resource. For example, to launch an instance into a particular compartment, specify that compartment's OCID in the `LaunchInstance` request. You can't move an existing resource from one compartment to another. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, -see [Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def compartment_group(): pass -@click.command(cli_util.override('tag_group.command_name', 'tag'), cls=CommandGroupWithAlias, help="""A tag definition that belongs to a specific tag namespace. "Defined tags" must be set up in your tenancy before -you can apply them to resources. -For more information, see [Managing Tags and Tag Namespaces].""") +@click.command(cli_util.override('tag_group.command_name', 'tag'), cls=CommandGroupWithAlias, help="""A tag definition that belongs to a specific tag namespace. \"Defined tags\" must be set up in your tenancy before you can apply them to resources. For more information, see [Managing Tags and Tag Namespaces].""") @cli_util.help_option_group def tag_group(): pass -@click.command(cli_util.override('dynamic_group_group.command_name', 'dynamic-group'), cls=CommandGroupWithAlias, help="""An dynamic group defines a matching rule. Every bare metal/vm instance is deployed with an instance certificate. -The certificate contains metadata about the instance. It contains the instance OCID and the compartment OCID, along -with a few other optional properties. When an API call is made using this instance certificate as the authenticator, -the certificate may be matched to one or multiple dynamic groups. Depending on policies written against these -dynamic groups, the instance will get access to that API. +@click.command(cli_util.override('dynamic_group_group.command_name', 'dynamic-group'), cls=CommandGroupWithAlias, help="""An dynamic group defines a matching rule. Every bare metal/vm instance is deployed with an instance certificate. The certificate contains metadata about the instance. It contains the instance OCID and the compartment OCID, along with a few other optional properties. When an API call is made using this instance certificate as the authenticator, the certificate may be matched to one or multiple dynamic groups. Depending on policies written against these dynamic groups, the instance will get access to that API. -This works like regular user/group memebership. But in that case the membership is a static relationship, whereas -in dynamic group, the membership of an instance certificate to dynamic groups are determined during runtime.""") +This works like regular user/group memebership. But in that case the membership is a static relationship, whereas in dynamic group, the membership of an instance certificate to dynamic groups are determined during runtime.""") @cli_util.help_option_group def dynamic_group_group(): pass -@click.command(cli_util.override('region_group.command_name', 'region'), cls=CommandGroupWithAlias, help="""A localized geographic area, such as Phoenix, AZ. Oracle Cloud Infrastructure is hosted in regions and Availability -Domains. A region is composed of several Availability Domains. An Availability Domain is one or more data centers -located within a region. For more information, see [Regions and Availability Domains]. +@click.command(cli_util.override('region_group.command_name', 'region'), cls=CommandGroupWithAlias, help="""A localized geographic area, such as Phoenix, AZ. Oracle Cloud Infrastructure is hosted in regions and Availability Domains. A region is composed of several Availability Domains. An Availability Domain is one or more data centers located within a region. For more information, see [Regions and Availability Domains]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, -see [Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def region_group(): pass -@click.command(cli_util.override('swift_password_group.command_name', 'swift-password'), cls=CommandGroupWithAlias, help="""Swift is the OpenStack object storage service. A `SwiftPassword` is an Oracle-provided password for using a -Swift client with the Oracle Cloud Infrastructure Object Storage Service. This password is associated with -the user's Console login. Swift passwords never expire. A user can have up to two Swift passwords at a time. +@click.command(cli_util.override('swift_password_group.command_name', 'swift-password'), cls=CommandGroupWithAlias, help="""Swift is the OpenStack object storage service. A `SwiftPassword` is an Oracle-provided password for using a Swift client with the Oracle Cloud Infrastructure Object Storage Service. This password is associated with the user's Console login. Swift passwords never expire. A user can have up to two Swift passwords at a time. **Note:** The password is always an Oracle-generated string; you can't change it to a string of your choice. @@ -198,58 +144,33 @@ def swift_password_group(): pass -@click.command(cli_util.override('user_group.command_name', 'user'), cls=CommandGroupWithAlias, help="""An individual employee or system that needs to manage or use your company's Oracle Cloud Infrastructure -resources. Users might need to launch instances, manage remote disks, work with your cloud network, etc. Users -have one or more IAM Service credentials ([ApiKey], -[UIPassword], and [SwiftPassword]). -For more information, see [User Credentials]). End users of your -application are not typically IAM Service users. For conceptual information about users and other IAM Service -components, see [Overview of the IAM Service]. +@click.command(cli_util.override('user_group.command_name', 'user'), cls=CommandGroupWithAlias, help="""An individual employee or system that needs to manage or use your company's Oracle Cloud Infrastructure resources. Users might need to launch instances, manage remote disks, work with your cloud network, etc. Users have one or more IAM Service credentials ([ApiKey], [UIPassword], and [SwiftPassword]). For more information, see [User Credentials]). End users of your application are not typically IAM Service users. For conceptual information about users and other IAM Service components, see [Overview of the IAM Service]. -These users are created directly within the Oracle Cloud Infrastructure system, via the IAM service. -They are different from *federated users*, who authenticate themselves to the Oracle Cloud Infrastructure -Console via an identity provider. For more information, see -[Identity Providers and Federation]. +These users are created directly within the Oracle Cloud Infrastructure system, via the IAM service. They are different from *federated users*, who authenticate themselves to the Oracle Cloud Infrastructure Console via an identity provider. For more information, see [Identity Providers and Federation]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, -see [Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def user_group(): pass -@click.command(cli_util.override('group_group.command_name', 'group'), cls=CommandGroupWithAlias, help="""A collection of users who all need the same type of access to a particular set of resources or compartment. -For conceptual information about groups and other IAM Service components, see -[Overview of the IAM Service]. +@click.command(cli_util.override('group_group.command_name', 'group'), cls=CommandGroupWithAlias, help="""A collection of users who all need the same type of access to a particular set of resources or compartment. For conceptual information about groups and other IAM Service components, see [Overview of the IAM Service]. -If you're federating with an identity provider (IdP), you need to create mappings between the groups -defined in the IdP and groups you define in the IAM service. For more information, see -[Identity Providers and Federation]. Also see -[IdentityProvider] and -[IdpGroupMapping]. +If you're federating with an identity provider (IdP), you need to create mappings between the groups defined in the IdP and groups you define in the IAM service. For more information, see [Identity Providers and Federation]. Also see [IdentityProvider] and [IdpGroupMapping]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, -see [Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def group_group(): pass -@click.command(cli_util.override('policy_group.command_name', 'policy'), cls=CommandGroupWithAlias, help="""A document that specifies the type of access a group has to the resources in a compartment. For information about -policies and other IAM Service components, see -[Overview of the IAM Service]. If you're new to policies, see -[Getting Started with Policies]. +@click.command(cli_util.override('policy_group.command_name', 'policy'), cls=CommandGroupWithAlias, help="""A document that specifies the type of access a group has to the resources in a compartment. For information about policies and other IAM Service components, see [Overview of the IAM Service]. If you're new to policies, see [Getting Started with Policies]. -The word "policy" is used by people in different ways: +The word \"policy\" is used by people in different ways: - * An individual statement written in the policy language - * A collection of statements in a single, named "policy" document (which has an Oracle Cloud ID (OCID) assigned to it) - * The overall body of policies your organization uses to control access to resources + * An individual statement written in the policy language * A collection of statements in a single, named \"policy\" document (which has an Oracle Cloud ID (OCID) assigned to it) * The overall body of policies your organization uses to control access to resources -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator.""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator.""") @cli_util.help_option_group def policy_group(): pass @@ -1016,6 +937,18 @@ def delete_dynamic_group(ctx, from_json, wait_for_state, max_wait_seconds, wait_ click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_dynamic_group, dynamic_group_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 Exception 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) @@ -1059,6 +992,18 @@ def delete_group(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_group, group_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 Exception 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) @@ -1102,6 +1047,18 @@ def delete_identity_provider(ctx, from_json, wait_for_state, max_wait_seconds, w click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_identity_provider, identity_provider_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 Exception 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) @@ -1174,6 +1131,18 @@ def delete_policy(ctx, from_json, wait_for_state, max_wait_seconds, wait_interva click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_policy, policy_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 Exception 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) @@ -1246,6 +1215,18 @@ def delete_user(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_ click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_user, user_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 Exception 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) diff --git a/src/oci_cli/generated/loadbalancer_cli.py b/src/oci_cli/generated/loadbalancer_cli.py index c18512706..06f1c00a2 100644 --- a/src/oci_cli/generated/loadbalancer_cli.py +++ b/src/oci_cli/generated/loadbalancer_cli.py @@ -20,51 +20,37 @@ def lb_group(): pass -@click.command(cli_util.override('load_balancer_group.command_name', 'load-balancer'), cls=CommandGroupWithAlias, help="""The properties that define a load balancer. For more information, see -[Managing a Load Balancer]. +@click.command(cli_util.override('load_balancer_group.command_name', 'load-balancer'), cls=CommandGroupWithAlias, help="""The properties that define a load balancer. For more information, see [Managing a Load Balancer]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies]. +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies]. -For information about endpoints and signing API requests, see -[About the API]. For information about available SDKs and tools, see -[SDKS and Other Tools].""") +For information about endpoints and signing API requests, see [About the API]. For information about available SDKs and tools, see [SDKS and Other Tools].""") @cli_util.help_option_group def load_balancer_group(): pass -@click.command(cli_util.override('load_balancer_shape_group.command_name', 'load-balancer-shape'), cls=CommandGroupWithAlias, help="""A shape is a template that determines the total pre-provisioned bandwidth (ingress plus egress) for the -load balancer. +@click.command(cli_util.override('load_balancer_shape_group.command_name', 'load-balancer-shape'), cls=CommandGroupWithAlias, help="""A shape is a template that determines the total pre-provisioned bandwidth (ingress plus egress) for the load balancer. -Note that the pre-provisioned maximum capacity applies to aggregated connections, not to a single client -attempting to use the full bandwidth.""") +Note that the pre-provisioned maximum capacity applies to aggregated connections, not to a single client attempting to use the full bandwidth.""") @cli_util.help_option_group def load_balancer_shape_group(): pass -@click.command(cli_util.override('certificate_group.command_name', 'certificate'), cls=CommandGroupWithAlias, help="""The configuration details of a listener certificate bundle. -For more information on SSL certficate configuration, see -[Managing SSL Certificates].""") +@click.command(cli_util.override('certificate_group.command_name', 'certificate'), cls=CommandGroupWithAlias, help="""The configuration details of a listener certificate bundle. For more information on SSL certficate configuration, see [Managing SSL Certificates].""") @cli_util.help_option_group def certificate_group(): pass -@click.command(cli_util.override('listener_group.command_name', 'listener'), cls=CommandGroupWithAlias, help="""The listener's configuration. -For more information on backend set configuration, see -[Managing Load Balancer Listeners].""") +@click.command(cli_util.override('listener_group.command_name', 'listener'), cls=CommandGroupWithAlias, help="""The listener's configuration. For more information on backend set configuration, see [Managing Load Balancer Listeners].""") @cli_util.help_option_group def listener_group(): pass -@click.command(cli_util.override('work_request_group.command_name', 'work-request'), cls=CommandGroupWithAlias, help="""Many of the API requests you use to create and configure load balancing do not take effect immediately. -In these cases, the request spawns an asynchronous work flow to fulfill the request. WorkRequest objects provide visibility -for in-progress work flows. -For more information about work requests, see [Viewing the State of a Work Request].""") +@click.command(cli_util.override('work_request_group.command_name', 'work-request'), cls=CommandGroupWithAlias, help="""Many of the API requests you use to create and configure load balancing do not take effect immediately. In these cases, the request spawns an asynchronous work flow to fulfill the request. WorkRequest objects provide visibility for in-progress work flows. For more information about work requests, see [Viewing the State of a Work Request].""") @cli_util.help_option_group def work_request_group(): pass @@ -72,20 +58,24 @@ def work_request_group(): @click.command(cli_util.override('backend_set_health_group.command_name', 'backend-set-health'), cls=CommandGroupWithAlias, help="""The health status details for a backend set. -This object does not explicitly enumerate backend servers with a status of `OK`. However, they are included in the -`totalBackendCount` sum.""") +This object does not explicitly enumerate backend servers with a status of `OK`. However, they are included in the `totalBackendCount` sum.""") @cli_util.help_option_group def backend_set_health_group(): pass -@click.command(cli_util.override('health_checker_group.command_name', 'health-checker'), cls=CommandGroupWithAlias, help="""The health check policy configuration. -For more information, see [Editing Health Check Policies].""") +@click.command(cli_util.override('health_checker_group.command_name', 'health-checker'), cls=CommandGroupWithAlias, help="""The health check policy configuration. For more information, see [Editing Health Check Policies].""") @cli_util.help_option_group def health_checker_group(): pass +@click.command(cli_util.override('path_route_set_group.command_name', 'path-route-set'), cls=CommandGroupWithAlias, help="""A named set of path route rules. For more information, see [Managing Request Routing].""") +@cli_util.help_option_group +def path_route_set_group(): + pass + + @click.command(cli_util.override('load_balancer_protocol_group.command_name', 'load-balancer-protocol'), cls=CommandGroupWithAlias, help="""The protocol that defines the type of traffic accepted by a listener.""") @cli_util.help_option_group def load_balancer_protocol_group(): @@ -94,16 +84,13 @@ def load_balancer_protocol_group(): @click.command(cli_util.override('load_balancer_health_group.command_name', 'load-balancer-health'), cls=CommandGroupWithAlias, help="""The health status details for the specified load balancer. -This object does not explicitly enumerate backend sets with a status of `OK`. However, they are included in the -`totalBackendSetCount` sum.""") +This object does not explicitly enumerate backend sets with a status of `OK`. However, they are included in the `totalBackendSetCount` sum.""") @cli_util.help_option_group def load_balancer_health_group(): pass -@click.command(cli_util.override('load_balancer_policy_group.command_name', 'load-balancer-policy'), cls=CommandGroupWithAlias, help="""A policy that determines how traffic is distributed among backend servers. -For more information on load balancing policies, see -[How Load Balancing Policies Work].""") +@click.command(cli_util.override('load_balancer_policy_group.command_name', 'load-balancer-policy'), cls=CommandGroupWithAlias, help="""A policy that determines how traffic is distributed among backend servers. For more information on load balancing policies, see [How Load Balancing Policies Work].""") @cli_util.help_option_group def load_balancer_policy_group(): pass @@ -115,16 +102,13 @@ def backend_health_group(): pass -@click.command(cli_util.override('backend_set_group.command_name', 'backend-set'), cls=CommandGroupWithAlias, help="""The configuration of a load balancer backend set. -For more information on backend set configuration, see -[Managing Backend Sets].""") +@click.command(cli_util.override('backend_set_group.command_name', 'backend-set'), cls=CommandGroupWithAlias, help="""The configuration of a load balancer backend set. For more information on backend set configuration, see [Managing Backend Sets].""") @cli_util.help_option_group def backend_set_group(): pass -@click.command(cli_util.override('backend_group.command_name', 'backend'), cls=CommandGroupWithAlias, help="""The configuration of a backend server that is a member of a load balancer backend set. -For more information, see [Managing Backend Servers].""") +@click.command(cli_util.override('backend_group.command_name', 'backend'), cls=CommandGroupWithAlias, help="""The configuration of a backend server that is a member of a load balancer backend set. For more information, see [Managing Backend Servers].""") @cli_util.help_option_group def backend_group(): pass @@ -137,6 +121,7 @@ def backend_group(): lb_group.add_command(work_request_group) lb_group.add_command(backend_set_health_group) lb_group.add_command(health_checker_group) +lb_group.add_command(path_route_set_group) lb_group.add_command(load_balancer_protocol_group) lb_group.add_command(load_balancer_health_group) lb_group.add_command(load_balancer_policy_group) @@ -391,6 +376,9 @@ def create_certificate(ctx, from_json, wait_for_state, max_wait_seconds, wait_in Example: `HTTP` [required]""") @click.option('--load-balancer-id', callback=cli_util.handle_required_param, help="""The [OCID] of the load balancer on which to add a listener. [required]""") @click.option('--connection-configuration', callback=cli_util.handle_optional_param, type=custom_types.CLI_COMPLEX_TYPE, help="""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@click.option('--path-route-set-name', callback=cli_util.handle_optional_param, help="""The name of the set of path-based routing rules, [PathRouteSet], applied to this listener's traffic. + +Example: `path-route-set-001`""") @click.option('--ssl-configuration', callback=cli_util.handle_optional_param, type=custom_types.CLI_COMPLEX_TYPE, help="""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) @click.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "FAILED", "SUCCEEDED"]), callback=cli_util.handle_optional_param, 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.""") @click.option('--max-wait-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") @@ -400,7 +388,7 @@ def create_certificate(ctx, from_json, wait_for_state, max_wait_seconds, wait_in @click.pass_context @json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'connection-configuration': {'module': 'load_balancer', 'class': 'ConnectionConfiguration'}, 'ssl-configuration': {'module': 'load_balancer', 'class': 'SSLConfigurationDetails'}}) @cli_util.wrap_exceptions -def create_listener(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, default_backend_set_name, name, port, protocol, load_balancer_id, connection_configuration, ssl_configuration): +def create_listener(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, default_backend_set_name, name, port, protocol, load_balancer_id, connection_configuration, path_route_set_name, ssl_configuration): if isinstance(load_balancer_id, six.string_types) and len(load_balancer_id.strip()) == 0: raise click.UsageError('Parameter --load-balancer-id cannot be whitespace or empty string') @@ -416,6 +404,9 @@ def create_listener(ctx, from_json, wait_for_state, max_wait_seconds, wait_inter if connection_configuration is not None: details['connectionConfiguration'] = cli_util.parse_json_parameter("connection_configuration", connection_configuration) + if path_route_set_name is not None: + details['pathRouteSetName'] = path_route_set_name + if ssl_configuration is not None: details['sslConfiguration'] = cli_util.parse_json_parameter("ssl_configuration", ssl_configuration) @@ -483,15 +474,18 @@ def create_listener(ctx, from_json, wait_for_state, max_wait_seconds, wait_inter @click.option('--listeners', callback=cli_util.handle_optional_param, type=custom_types.CLI_COMPLEX_TYPE, help=""" This option is a JSON dictionary of type dict(str, ListenerDetails). For documentation on ListenerDetails please see our API reference: https://docs.us-phoenix-1.oraclecloud.com/api/#.""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@click.option('--path-route-sets', callback=cli_util.handle_optional_param, type=custom_types.CLI_COMPLEX_TYPE, help=""" + +This option is a JSON dictionary of type dict(str, PathRouteSetDetails). For documentation on PathRouteSetDetails please see our API reference: https://docs.us-phoenix-1.oraclecloud.com/api/#.""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) @click.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "FAILED", "SUCCEEDED"]), callback=cli_util.handle_optional_param, 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.""") @click.option('--max-wait-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") @click.option('--wait-interval-seconds', type=click.INT, callback=cli_util.handle_optional_param, 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({'backend-sets': {'module': 'load_balancer', 'class': 'dict(str, BackendSetDetails)'}, 'certificates': {'module': 'load_balancer', 'class': 'dict(str, CertificateDetails)'}, 'listeners': {'module': 'load_balancer', 'class': 'dict(str, ListenerDetails)'}, 'subnet-ids': {'module': 'load_balancer', 'class': 'list[string]'}}) +@json_skeleton_utils.get_cli_json_input_option({'backend-sets': {'module': 'load_balancer', 'class': 'dict(str, BackendSetDetails)'}, 'certificates': {'module': 'load_balancer', 'class': 'dict(str, CertificateDetails)'}, 'listeners': {'module': 'load_balancer', 'class': 'dict(str, ListenerDetails)'}, 'path-route-sets': {'module': 'load_balancer', 'class': 'dict(str, PathRouteSetDetails)'}, 'subnet-ids': {'module': 'load_balancer', 'class': 'list[string]'}}) @cli_util.help_option @click.pass_context -@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'backend-sets': {'module': 'load_balancer', 'class': 'dict(str, BackendSetDetails)'}, 'certificates': {'module': 'load_balancer', 'class': 'dict(str, CertificateDetails)'}, 'listeners': {'module': 'load_balancer', 'class': 'dict(str, ListenerDetails)'}, 'subnet-ids': {'module': 'load_balancer', 'class': 'list[string]'}}) +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'backend-sets': {'module': 'load_balancer', 'class': 'dict(str, BackendSetDetails)'}, 'certificates': {'module': 'load_balancer', 'class': 'dict(str, CertificateDetails)'}, 'listeners': {'module': 'load_balancer', 'class': 'dict(str, ListenerDetails)'}, 'path-route-sets': {'module': 'load_balancer', 'class': 'dict(str, PathRouteSetDetails)'}, 'subnet-ids': {'module': 'load_balancer', 'class': 'list[string]'}}) @cli_util.wrap_exceptions -def create_load_balancer(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, compartment_id, display_name, shape_name, subnet_ids, backend_sets, certificates, is_private, listeners): +def create_load_balancer(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, compartment_id, display_name, shape_name, subnet_ids, backend_sets, certificates, is_private, listeners, path_route_sets): kwargs = {} kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) @@ -513,6 +507,9 @@ def create_load_balancer(ctx, from_json, wait_for_state, max_wait_seconds, wait_ if listeners is not None: details['listeners'] = cli_util.parse_json_parameter("listeners", listeners) + if path_route_sets is not None: + details['pathRouteSets'] = cli_util.parse_json_parameter("path_route_sets", path_route_sets) + client = cli_util.build_client('load_balancer', ctx) result = client.create_load_balancer( create_load_balancer_details=details, @@ -539,6 +536,56 @@ def create_load_balancer(ctx, from_json, wait_for_state, max_wait_seconds, wait_ cli_util.render_response(result, ctx) +@path_route_set_group.command(name=cli_util.override('create_path_route_set.command_name', 'create'), help="""Adds a path route set to a load balancer. For more information, see [Managing Request Routing].""") +@click.option('--name', callback=cli_util.handle_required_param, help="""The name for this set of path route rules. It must be unique and it cannot be changed. Avoid entering confidential information. + +Example: `path-route-set-001` [required]""") +@click.option('--path-routes', callback=cli_util.handle_required_param, type=custom_types.CLI_COMPLEX_TYPE, help="""The set of path route rules. [required]""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@click.option('--load-balancer-id', callback=cli_util.handle_required_param, help="""The [OCID] of the load balancer to add the path route set to. [required]""") +@click.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "FAILED", "SUCCEEDED"]), callback=cli_util.handle_optional_param, 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.""") +@click.option('--max-wait-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") +@click.option('--wait-interval-seconds', type=click.INT, callback=cli_util.handle_optional_param, 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({'path-routes': {'module': 'load_balancer', 'class': 'list[PathRoute]'}}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'path-routes': {'module': 'load_balancer', 'class': 'list[PathRoute]'}}) +@cli_util.wrap_exceptions +def create_path_route_set(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, name, path_routes, load_balancer_id): + + if isinstance(load_balancer_id, six.string_types) and len(load_balancer_id.strip()) == 0: + raise click.UsageError('Parameter --load-balancer-id cannot be whitespace or empty string') + kwargs = {} + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + + details = {} + details['name'] = name + details['pathRoutes'] = cli_util.parse_json_parameter("path_routes", path_routes) + + client = cli_util.build_client('load_balancer', ctx) + result = client.create_path_route_set( + load_balancer_id=load_balancer_id, + create_path_route_set_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: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds: + 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, retry_utils.call_funtion_with_default_retries(client.get_work_request, result.headers['opc-work-request-id']), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + except Exception 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) + else: + click.echo('Unable to wait for the work request to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + @backend_group.command(name=cli_util.override('delete_backend.command_name', 'delete'), help="""Removes a backend server from a given load balancer and backend set.""") @click.option('--load-balancer-id', callback=cli_util.handle_required_param, help="""The [OCID] of the load balancer associated with the backend set and server. [required]""") @click.option('--backend-set-name', callback=cli_util.handle_required_param, help="""The name of the backend set associated with the backend server. @@ -781,6 +828,56 @@ def delete_load_balancer(ctx, from_json, wait_for_state, max_wait_seconds, wait_ cli_util.render_response(result, ctx) +@path_route_set_group.command(name=cli_util.override('delete_path_route_set.command_name', 'delete'), help="""Deletes a path route set from the specified load balancer. + +To delete a path route rule from a path route set, use the [UpdatePathRouteSet] operation.""") +@click.option('--load-balancer-id', callback=cli_util.handle_required_param, help="""The [OCID] of the load balancer associated with the path route set to delete. [required]""") +@click.option('--path-route-set-name', callback=cli_util.handle_required_param, help="""The name of the path route set to delete. + +Example: `path-route-set-001` [required]""") +@cli_util.confirm_delete_option +@click.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "FAILED", "SUCCEEDED"]), callback=cli_util.handle_optional_param, 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.""") +@click.option('--max-wait-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") +@click.option('--wait-interval-seconds', type=click.INT, callback=cli_util.handle_optional_param, 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 delete_path_route_set(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_seconds, load_balancer_id, path_route_set_name): + + if isinstance(load_balancer_id, six.string_types) and len(load_balancer_id.strip()) == 0: + raise click.UsageError('Parameter --load-balancer-id cannot be whitespace or empty string') + + if isinstance(path_route_set_name, six.string_types) and len(path_route_set_name.strip()) == 0: + raise click.UsageError('Parameter --path-route-set-name 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('load_balancer', ctx) + result = client.delete_path_route_set( + load_balancer_id=load_balancer_id, + path_route_set_name=path_route_set_name, + **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: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds: + 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, retry_utils.call_funtion_with_default_retries(client.get_work_request, result.headers['opc-work-request-id']), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + except Exception 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. Please retrieve the work request to find its current state', file=sys.stderr) + else: + click.echo('Unable to wait for the work request to enter the specified state', file=sys.stderr) + cli_util.render_response(result, ctx) + + @backend_group.command(name=cli_util.override('get_backend.command_name', 'get'), help="""Gets the specified backend server's configuration information.""") @click.option('--load-balancer-id', callback=cli_util.handle_required_param, help="""The [OCID] of the load balancer associated with the backend set and server. [required]""") @click.option('--backend-set-name', callback=cli_util.handle_required_param, help="""The name of the backend set that includes the backend server. @@ -977,6 +1074,34 @@ def get_load_balancer_health(ctx, from_json, load_balancer_id): cli_util.render_response(result, ctx) +@path_route_set_group.command(name=cli_util.override('get_path_route_set.command_name', 'get'), help="""Gets the specified path route set's configuration information.""") +@click.option('--load-balancer-id', callback=cli_util.handle_required_param, help="""The [OCID] of the specified load balancer. [required]""") +@click.option('--path-route-set-name', callback=cli_util.handle_required_param, help="""The name of the path route set to retrieve. + +Example: `path-route-set-001` [required]""") +@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': 'load_balancer', 'class': 'PathRouteSet'}) +@cli_util.wrap_exceptions +def get_path_route_set(ctx, from_json, load_balancer_id, path_route_set_name): + + if isinstance(load_balancer_id, six.string_types) and len(load_balancer_id.strip()) == 0: + raise click.UsageError('Parameter --load-balancer-id cannot be whitespace or empty string') + + if isinstance(path_route_set_name, six.string_types) and len(path_route_set_name.strip()) == 0: + raise click.UsageError('Parameter --path-route-set-name 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('load_balancer', ctx) + result = client.get_path_route_set( + load_balancer_id=load_balancer_id, + path_route_set_name=path_route_set_name, + **kwargs + ) + cli_util.render_response(result, ctx) + + @work_request_group.command(name=cli_util.override('get_work_request.command_name', 'get'), help="""Gets the details of a work request.""") @click.option('--work-request-id', callback=cli_util.handle_required_param, help="""The [OCID] of the work request to retrieve. [required]""") @json_skeleton_utils.get_cli_json_input_option({}) @@ -1187,6 +1312,27 @@ def list_load_balancers(ctx, from_json, all_pages, page_size, compartment_id, li cli_util.render_response(result, ctx) +@path_route_set_group.command(name=cli_util.override('list_path_route_sets.command_name', 'list'), help="""Lists all path route sets associated with the specified load balancer.""") +@click.option('--load-balancer-id', callback=cli_util.handle_required_param, help="""The [OCID] of the load balancer associated with the path route sets to retrieve. [required]""") +@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': 'load_balancer', 'class': 'list[PathRouteSet]'}) +@cli_util.wrap_exceptions +def list_path_route_sets(ctx, from_json, load_balancer_id): + + if isinstance(load_balancer_id, six.string_types) and len(load_balancer_id.strip()) == 0: + raise click.UsageError('Parameter --load-balancer-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('load_balancer', ctx) + result = client.list_path_route_sets( + load_balancer_id=load_balancer_id, + **kwargs + ) + cli_util.render_response(result, ctx) + + @load_balancer_policy_group.command(name=cli_util.override('list_policies.command_name', 'list-policies'), help="""Lists the available load balancer policies.""") @click.option('--compartment-id', callback=cli_util.handle_required_param, help="""The [OCID] of the compartment containing the load balancer policies to list. [required]""") @click.option('--limit', callback=cli_util.handle_optional_param, type=click.INT, help="""The maximum number of items to return in a paginated \"List\" call. @@ -1640,6 +1786,9 @@ def update_health_checker(ctx, from_json, wait_for_state, max_wait_seconds, wait Example: `My listener` [required]""") @click.option('--connection-configuration', callback=cli_util.handle_optional_param, type=custom_types.CLI_COMPLEX_TYPE, help="""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@click.option('--path-route-set-name', callback=cli_util.handle_optional_param, help="""The name of the set of path-based routing rules, [PathRouteSet], applied to this listener's traffic. + +Example: `path-route-set-001`""") @click.option('--ssl-configuration', callback=cli_util.handle_optional_param, type=custom_types.CLI_COMPLEX_TYPE, help="""""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) @click.option('--force', callback=cli_util.handle_optional_param, help="""Perform update without prompting for confirmation.""", is_flag=True) @click.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "FAILED", "SUCCEEDED"]), callback=cli_util.handle_optional_param, 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.""") @@ -1650,7 +1799,7 @@ def update_health_checker(ctx, from_json, wait_for_state, max_wait_seconds, wait @click.pass_context @json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'connection-configuration': {'module': 'load_balancer', 'class': 'ConnectionConfiguration'}, 'ssl-configuration': {'module': 'load_balancer', 'class': 'SSLConfigurationDetails'}}) @cli_util.wrap_exceptions -def update_listener(ctx, from_json, force, wait_for_state, max_wait_seconds, wait_interval_seconds, default_backend_set_name, port, protocol, load_balancer_id, listener_name, connection_configuration, ssl_configuration): +def update_listener(ctx, from_json, force, wait_for_state, max_wait_seconds, wait_interval_seconds, default_backend_set_name, port, protocol, load_balancer_id, listener_name, connection_configuration, path_route_set_name, ssl_configuration): if isinstance(load_balancer_id, six.string_types) and len(load_balancer_id.strip()) == 0: raise click.UsageError('Parameter --load-balancer-id cannot be whitespace or empty string') @@ -1672,6 +1821,9 @@ def update_listener(ctx, from_json, force, wait_for_state, max_wait_seconds, wai if connection_configuration is not None: details['connectionConfiguration'] = cli_util.parse_json_parameter("connection_configuration", connection_configuration) + if path_route_set_name is not None: + details['pathRouteSetName'] = path_route_set_name + if ssl_configuration is not None: details['sslConfiguration'] = cli_util.parse_json_parameter("ssl_configuration", ssl_configuration) @@ -1749,3 +1901,63 @@ def update_load_balancer(ctx, from_json, wait_for_state, max_wait_seconds, wait_ else: click.echo('Unable to wait for the work request to enter the specified state', file=sys.stderr) cli_util.render_response(result, ctx) + + +@path_route_set_group.command(name=cli_util.override('update_path_route_set.command_name', 'update'), help="""Overwrites an existing path route set on the specified load balancer. Use this operation to add, delete, or alter path route rules in a path route set. + +To add a new path route rule to a path route set, the `pathRoutes` in the [UpdatePathRouteSetDetails] object must include both the new path route rule to add and the existing path route rules to retain.""") +@click.option('--path-routes', callback=cli_util.handle_required_param, type=custom_types.CLI_COMPLEX_TYPE, help="""The set of path route rules. [required]""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) +@click.option('--load-balancer-id', callback=cli_util.handle_required_param, help="""The [OCID] of the load balancer associated with the path route set to update. [required]""") +@click.option('--path-route-set-name', callback=cli_util.handle_required_param, help="""The name of the path route set to update. + +Example: `path-route-set-001` [required]""") +@click.option('--force', callback=cli_util.handle_optional_param, help="""Perform update without prompting for confirmation.""", is_flag=True) +@click.option('--wait-for-state', type=custom_types.CliCaseInsensitiveChoice(["ACCEPTED", "IN_PROGRESS", "FAILED", "SUCCEEDED"]), callback=cli_util.handle_optional_param, 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.""") +@click.option('--max-wait-seconds', type=click.INT, callback=cli_util.handle_optional_param, help="""The maximum time to wait for the work request to reach the state defined by --wait-for-state. Defaults to 1200 seconds.""") +@click.option('--wait-interval-seconds', type=click.INT, callback=cli_util.handle_optional_param, 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({'path-routes': {'module': 'load_balancer', 'class': 'list[PathRoute]'}}) +@cli_util.help_option +@click.pass_context +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'path-routes': {'module': 'load_balancer', 'class': 'list[PathRoute]'}}) +@cli_util.wrap_exceptions +def update_path_route_set(ctx, from_json, force, wait_for_state, max_wait_seconds, wait_interval_seconds, path_routes, load_balancer_id, path_route_set_name): + + if isinstance(load_balancer_id, six.string_types) and len(load_balancer_id.strip()) == 0: + raise click.UsageError('Parameter --load-balancer-id cannot be whitespace or empty string') + + if isinstance(path_route_set_name, six.string_types) and len(path_route_set_name.strip()) == 0: + raise click.UsageError('Parameter --path-route-set-name cannot be whitespace or empty string') + if not force: + if path_routes: + if not click.confirm("WARNING: Updates to path-routes will replace any existing values. Are you sure you want to continue?"): + ctx.abort() + kwargs = {} + kwargs['opc_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) + + details = {} + details['pathRoutes'] = cli_util.parse_json_parameter("path_routes", path_routes) + + client = cli_util.build_client('load_balancer', ctx) + result = client.update_path_route_set( + load_balancer_id=load_balancer_id, + path_route_set_name=path_route_set_name, + update_path_route_set_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: + wait_period_kwargs['max_wait_seconds'] = max_wait_seconds + if wait_interval_seconds: + 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, retry_utils.call_funtion_with_default_retries(client.get_work_request, result.headers['opc-work-request-id']), 'lifecycle_state', wait_for_state, **wait_period_kwargs) + except Exception 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) + else: + 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/src/oci_cli/generated/objectstorage_cli.py b/src/oci_cli/generated/objectstorage_cli.py index be8af5e98..3cd6f72be 100644 --- a/src/oci_cli/generated/objectstorage_cli.py +++ b/src/oci_cli/generated/objectstorage_cli.py @@ -20,32 +20,23 @@ def os_group(): pass -@click.command(cli_util.override('bucket_group.command_name', 'bucket'), cls=CommandGroupWithAlias, help="""A bucket is a container for storing objects in a compartment within a namespace. A bucket is associated with a single compartment. -The compartment has policies that indicate what actions a user can perform on a bucket and all the objects in the bucket. For more -information, see [Managing Buckets]. +@click.command(cli_util.override('bucket_group.command_name', 'bucket'), cls=CommandGroupWithAlias, help="""A bucket is a container for storing objects in a compartment within a namespace. A bucket is associated with a single compartment. The compartment has policies that indicate what actions a user can perform on a bucket and all the objects in the bucket. For more information, see [Managing Buckets]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def bucket_group(): pass -@click.command(cli_util.override('preauthenticated_request_group.command_name', 'preauthenticated-request'), cls=CommandGroupWithAlias, help="""Pre-authenticated requests provide a way to let users access a bucket or an object without having their own credentials. -When you create a pre-authenticated request, a unique URL is generated. Users in your organization, partners, or third -parties can use this URL to access the targets identified in the pre-authenticated request. See [Managing Access to Buckets and Objects]. +@click.command(cli_util.override('preauthenticated_request_group.command_name', 'preauthenticated-request'), cls=CommandGroupWithAlias, help="""Pre-authenticated requests provide a way to let users access a bucket or an object without having their own credentials. When you create a pre-authenticated request, a unique URL is generated. Users in your organization, partners, or third parties can use this URL to access the targets identified in the pre-authenticated request. See [Managing Access to Buckets and Objects]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. -If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def preauthenticated_request_group(): pass -@click.command(cli_util.override('object_group.command_name', 'object'), cls=CommandGroupWithAlias, help="""To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +@click.command(cli_util.override('object_group.command_name', 'object'), cls=CommandGroupWithAlias, help="""To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def object_group(): pass @@ -147,12 +138,14 @@ def commit_multipart_upload(ctx, from_json, namespace_name, bucket_name, object_ @click.option('--metadata', callback=cli_util.handle_optional_param, type=custom_types.CLI_COMPLEX_TYPE, help="""Arbitrary string, up to 4KB, of keys and values for user-defined metadata.""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) @click.option('--public-access-type', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["NoPublicAccess", "ObjectRead", "ObjectReadWithoutList"]), help="""The type of public access enabled on this bucket. A bucket is set to `NoPublicAccess` by default, which only allows an authenticated caller to access the bucket and its contents. When `ObjectRead` is enabled on the bucket, public access is allowed for the `GetObject`, `HeadObject`, and `ListObjects` operations. When `ObjectReadWithoutList` is enabled on the bucket, public access is allowed for the `GetObject` and `HeadObject` operations.""") @click.option('--storage-tier', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["Standard", "Archive"]), help="""The type of storage tier of this bucket. A bucket is set to 'Standard' tier by default, which means the bucket will be put in the standard storage tier. When 'Archive' tier type is set explicitly, the bucket is put in the Archive Storage tier. The 'storageTier' property is immutable after bucket is created.""") -@json_skeleton_utils.get_cli_json_input_option({'metadata': {'module': 'object_storage', 'class': 'dict(str, string)'}}) +@click.option('--freeform-tags', callback=cli_util.handle_optional_param, type=custom_types.CLI_COMPLEX_TYPE, help="""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) +@click.option('--defined-tags', callback=cli_util.handle_optional_param, type=custom_types.CLI_COMPLEX_TYPE, help="""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) +@json_skeleton_utils.get_cli_json_input_option({'metadata': {'module': 'object_storage', 'class': 'dict(str, string)'}, 'freeform-tags': {'module': 'object_storage', 'class': 'dict(str, string)'}, 'defined-tags': {'module': 'object_storage', '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={'metadata': {'module': 'object_storage', 'class': 'dict(str, string)'}}, output_type={'module': 'object_storage', 'class': 'Bucket'}) +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'metadata': {'module': 'object_storage', 'class': 'dict(str, string)'}, 'freeform-tags': {'module': 'object_storage', 'class': 'dict(str, string)'}, 'defined-tags': {'module': 'object_storage', 'class': 'dict(str, dict(str, object))'}}, output_type={'module': 'object_storage', 'class': 'Bucket'}) @cli_util.wrap_exceptions -def create_bucket(ctx, from_json, namespace_name, name, compartment_id, metadata, public_access_type, storage_tier): +def create_bucket(ctx, from_json, namespace_name, name, compartment_id, metadata, public_access_type, storage_tier, freeform_tags, defined_tags): if isinstance(namespace_name, six.string_types) and len(namespace_name.strip()) == 0: raise click.UsageError('Parameter --namespace-name cannot be whitespace or empty string') @@ -172,6 +165,12 @@ def create_bucket(ctx, from_json, namespace_name, name, compartment_id, metadata if storage_tier is not None: details['storageTier'] = storage_tier + 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('object_storage', ctx) result = client.create_bucket( namespace_name=namespace_name, @@ -588,6 +587,7 @@ def head_object(ctx, from_json, namespace_name, bucket_name, object_name, if_mat @click.option('--compartment-id', callback=cli_util.handle_required_param, help="""The ID of the compartment in which to list buckets. [required]""") @click.option('--limit', callback=cli_util.handle_optional_param, type=click.INT, help="""The maximum number of items to return.""") @click.option('--page', callback=cli_util.handle_optional_param, help="""The page at which to start retrieving results.""") +@click.option('--fields', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["tags"]), multiple=True, help="""Bucket summary in list of buckets includes the 'namespace', 'name', 'compartmentId', 'createdBy', 'timeCreated', and 'etag' fields. This parameter can also include 'tags' (freeformTags and definedTags). The only supported value of this parameter is 'tags' for now. Example 'tags'.""") @click.option('--all', 'all_pages', is_flag=True, callback=cli_util.handle_optional_param, help="""Fetches all pages of results. If you provide this option, then you cannot provide the --limit option.""") @click.option('--page-size', type=click.INT, callback=cli_util.handle_optional_param, 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({}) @@ -595,7 +595,7 @@ def head_object(ctx, from_json, namespace_name, bucket_name, object_name, if_mat @click.pass_context @json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}, output_type={'module': 'object_storage', 'class': 'list[BucketSummary]'}) @cli_util.wrap_exceptions -def list_buckets(ctx, from_json, all_pages, page_size, namespace_name, compartment_id, limit, page): +def list_buckets(ctx, from_json, all_pages, page_size, namespace_name, compartment_id, limit, page, fields): if all_pages and limit: raise click.UsageError('If you provide the --all option you cannot provide the --limit option') @@ -607,6 +607,8 @@ def list_buckets(ctx, from_json, all_pages, page_size, namespace_name, compartme kwargs['limit'] = limit if page is not None: kwargs['page'] = page + if fields is not None and len(fields) > 0: + kwargs['fields'] = fields kwargs['opc_client_request_id'] = cli_util.use_or_generate_request_id(ctx.obj['request_id']) client = cli_util.build_client('object_storage', ctx) if all_pages: @@ -974,16 +976,17 @@ def rename_object(ctx, from_json, namespace_name, bucket_name, source_name, new_ cli_util.render_response(result, ctx) -@object_group.command(name=cli_util.override('restore_objects.command_name', 'restore'), help="""Restore one or more objects specified by objectName parameter.""") +@object_group.command(name=cli_util.override('restore_objects.command_name', 'restore'), help="""Restore one or more objects specified by objectName parameter. By default object will be restored for 24 hours.Duration can be configured using hours parameter.""") @click.option('--namespace-name', callback=cli_util.handle_required_param, help="""The top-level namespace used for the request. [required]""") @click.option('--bucket-name', callback=cli_util.handle_required_param, help="""The name of the bucket. Avoid entering confidential information. Example: `my-new-bucket1` [required]""") @click.option('--object-name', callback=cli_util.handle_required_param, help="""A object which was in an archived state and need to be restored. [required]""") +@click.option('--hours', callback=cli_util.handle_optional_param, type=click.INT, help="""The number of hours for which this object will be restored. By default object will be restored for 24 hours.It can be configured using hours parameter.""") @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 restore_objects(ctx, from_json, namespace_name, bucket_name, object_name): +def restore_objects(ctx, from_json, namespace_name, bucket_name, object_name, hours): if isinstance(namespace_name, six.string_types) and len(namespace_name.strip()) == 0: raise click.UsageError('Parameter --namespace-name cannot be whitespace or empty string') @@ -996,6 +999,9 @@ def restore_objects(ctx, from_json, namespace_name, bucket_name, object_name): details = {} details['objectName'] = object_name + if hours is not None: + details['hours'] = hours + client = cli_util.build_client('object_storage', ctx) result = client.restore_objects( namespace_name=namespace_name, @@ -1012,13 +1018,15 @@ def restore_objects(ctx, from_json, namespace_name, bucket_name, object_name): @click.option('--compartment-id', callback=cli_util.handle_optional_param, help="""The compartmentId for the compartment to which the bucket is targeted to move to.""") @click.option('--metadata', callback=cli_util.handle_optional_param, type=custom_types.CLI_COMPLEX_TYPE, help="""Arbitrary string, up to 4KB, of keys and values for user-defined metadata.""" + custom_types.cli_complex_type.COMPLEX_TYPE_HELP) @click.option('--public-access-type', callback=cli_util.handle_optional_param, type=custom_types.CliCaseInsensitiveChoice(["NoPublicAccess", "ObjectRead", "ObjectReadWithoutList"]), help="""The type of public access enabled on this bucket. A bucket is set to `NoPublicAccess` by default, which only allows an authenticated caller to access the bucket and its contents. When `ObjectRead` is enabled on the bucket, public access is allowed for the `GetObject`, `HeadObject`, and `ListObjects` operations. When `ObjectReadWithoutList` is enabled on the bucket, public access is allowed for the `GetObject` and `HeadObject` operations.""") +@click.option('--freeform-tags', callback=cli_util.handle_optional_param, type=custom_types.CLI_COMPLEX_TYPE, help="""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) +@click.option('--defined-tags', callback=cli_util.handle_optional_param, type=custom_types.CLI_COMPLEX_TYPE, help="""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) @click.option('--if-match', callback=cli_util.handle_optional_param, help="""The entity tag to match. For creating and committing a multipart upload to an object, this is the entity tag of the target object. For uploading a part, this is the entity tag of the target part.""") -@json_skeleton_utils.get_cli_json_input_option({'metadata': {'module': 'object_storage', 'class': 'dict(str, string)'}}) +@json_skeleton_utils.get_cli_json_input_option({'metadata': {'module': 'object_storage', 'class': 'dict(str, string)'}, 'freeform-tags': {'module': 'object_storage', 'class': 'dict(str, string)'}, 'defined-tags': {'module': 'object_storage', '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={'metadata': {'module': 'object_storage', 'class': 'dict(str, string)'}}, output_type={'module': 'object_storage', 'class': 'Bucket'}) +@json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={'metadata': {'module': 'object_storage', 'class': 'dict(str, string)'}, 'freeform-tags': {'module': 'object_storage', 'class': 'dict(str, string)'}, 'defined-tags': {'module': 'object_storage', 'class': 'dict(str, dict(str, object))'}}, output_type={'module': 'object_storage', 'class': 'Bucket'}) @cli_util.wrap_exceptions -def update_bucket(ctx, from_json, namespace_name, bucket_name, compartment_id, metadata, public_access_type, if_match): +def update_bucket(ctx, from_json, namespace_name, bucket_name, compartment_id, metadata, public_access_type, freeform_tags, defined_tags, if_match): if isinstance(namespace_name, six.string_types) and len(namespace_name.strip()) == 0: raise click.UsageError('Parameter --namespace-name cannot be whitespace or empty string') @@ -1044,6 +1052,12 @@ def update_bucket(ctx, from_json, namespace_name, bucket_name, compartment_id, m if public_access_type is not None: details['publicAccessType'] = public_access_type + 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('object_storage', ctx) result = client.update_bucket( namespace_name=namespace_name, diff --git a/src/oci_cli/generated/virtualnetwork_cli.py b/src/oci_cli/generated/virtualnetwork_cli.py index 5ade08ce7..ce68ea00a 100644 --- a/src/oci_cli/generated/virtualnetwork_cli.py +++ b/src/oci_cli/generated/virtualnetwork_cli.py @@ -20,36 +20,25 @@ def virtual_network_group(): pass -@click.command(cli_util.override('subnet_group.command_name', 'subnet'), cls=CommandGroupWithAlias, help="""A logical subdivision of a VCN. Each subnet exists in a single Availability Domain and -consists of a contiguous range of IP addresses that do not overlap with -other subnets in the VCN. Example: 172.16.1.0/24. For more information, see -[Overview of the Networking Service] and -[VCNs and Subnets]. - -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +@click.command(cli_util.override('subnet_group.command_name', 'subnet'), cls=CommandGroupWithAlias, help="""A logical subdivision of a VCN. Each subnet exists in a single Availability Domain and consists of a contiguous range of IP addresses that do not overlap with other subnets in the VCN. Example: 172.16.1.0/24. For more information, see [Overview of the Networking Service] and [VCNs and Subnets]. + +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def subnet_group(): pass -@click.command(cli_util.override('drg_attachment_group.command_name', 'drg-attachment'), cls=CommandGroupWithAlias, help="""A link between a DRG and VCN. For more information, see -[Overview of the Networking Service].""") +@click.command(cli_util.override('drg_attachment_group.command_name', 'drg-attachment'), cls=CommandGroupWithAlias, help="""A link between a DRG and VCN. For more information, see [Overview of the Networking Service].""") @cli_util.help_option_group def drg_attachment_group(): pass -@click.command(cli_util.override('public_ip_group.command_name', 'public-ip'), cls=CommandGroupWithAlias, help="""A *public IP* is a conceptual term that refers to a public IP address and related properties. -The `publicIp` object is the API representation of a public IP. +@click.command(cli_util.override('public_ip_group.command_name', 'public-ip'), cls=CommandGroupWithAlias, help="""A *public IP* is a conceptual term that refers to a public IP address and related properties. The `publicIp` object is the API representation of a public IP. -There are two types of public IPs: -1. Ephemeral -2. Reserved +There are two types of public IPs: 1. Ephemeral 2. Reserved -For more information and comparison of the two types, -see [Public IP Addresses].""") +For more information and comparison of the two types, see [Public IP Addresses].""") @cli_util.help_option_group def public_ip_group(): pass @@ -61,8 +50,7 @@ def ip_sec_connection_device_config_group(): pass -@click.command(cli_util.override('fast_connect_provider_service_group.command_name', 'fast-connect-provider-service'), cls=CommandGroupWithAlias, help="""A service offering from a supported provider. For more information, -see [FastConnect Overview].""") +@click.command(cli_util.override('fast_connect_provider_service_group.command_name', 'fast-connect-provider-service'), cls=CommandGroupWithAlias, help="""A service offering from a supported provider. For more information, see [FastConnect Overview].""") @cli_util.help_option_group def fast_connect_provider_service_group(): pass @@ -74,41 +62,21 @@ def cross_connect_location_group(): pass -@click.command(cli_util.override('virtual_circuit_public_prefix_group.command_name', 'virtual-circuit-public-prefix'), cls=CommandGroupWithAlias, help="""A public IP prefix and its details. With a public virtual circuit, the customer -specifies the customer-owned public IP prefixes to advertise across the connection. -For more information, see [FastConnect Overview].""") +@click.command(cli_util.override('virtual_circuit_public_prefix_group.command_name', 'virtual-circuit-public-prefix'), cls=CommandGroupWithAlias, help="""A public IP prefix and its details. With a public virtual circuit, the customer specifies the customer-owned public IP prefixes to advertise across the connection. For more information, see [FastConnect Overview].""") @cli_util.help_option_group def virtual_circuit_public_prefix_group(): pass -@click.command(cli_util.override('private_ip_group.command_name', 'private-ip'), cls=CommandGroupWithAlias, help="""A *private IP* is a conceptual term that refers to a private IP address and related properties. -The `privateIp` object is the API representation of a private IP. - -Each instance has a *primary private IP* that is automatically created and -assigned to the primary VNIC during instance launch. If you add a secondary -VNIC to the instance, it also automatically gets a primary private IP. You -can't remove a primary private IP from its VNIC. The primary private IP is -automatically deleted when the VNIC is terminated. - -You can add *secondary private IPs* to a VNIC after it's created. For more -information, see the `privateIp` operations and also -[IP Addresses]. - -**Note:** Only -[ListPrivateIps] and -[GetPrivateIp] work with -*primary* private IPs. To create and update primary private IPs, you instead -work with instance and VNIC operations. For example, a primary private IP's -properties come from the values you specify in -[CreateVnicDetails] when calling either -[LaunchInstance] or -[AttachVnic]. To update the hostname -for a primary private IP, you use [UpdateVnic]. - -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +@click.command(cli_util.override('private_ip_group.command_name', 'private-ip'), cls=CommandGroupWithAlias, help="""A *private IP* is a conceptual term that refers to a private IP address and related properties. The `privateIp` object is the API representation of a private IP. + +Each instance has a *primary private IP* that is automatically created and assigned to the primary VNIC during instance launch. If you add a secondary VNIC to the instance, it also automatically gets a primary private IP. You can't remove a primary private IP from its VNIC. The primary private IP is automatically deleted when the VNIC is terminated. + +You can add *secondary private IPs* to a VNIC after it's created. For more information, see the `privateIp` operations and also [IP Addresses]. + +**Note:** Only [ListPrivateIps] and [GetPrivateIp] work with *primary* private IPs. To create and update primary private IPs, you instead work with instance and VNIC operations. For example, a primary private IP's properties come from the values you specify in [CreateVnicDetails] when calling either [LaunchInstance] or [AttachVnic]. To update the hostname for a primary private IP, you use [UpdateVnic]. + +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def private_ip_group(): pass @@ -116,37 +84,19 @@ def private_ip_group(): @click.command(cli_util.override('virtual_circuit_group.command_name', 'virtual-circuit'), cls=CommandGroupWithAlias, help="""For use with Oracle Cloud Infrastructure FastConnect. -A virtual circuit is an isolated network path that runs over one or more physical -network connections to provide a single, logical connection between the edge router -on the customer's existing network and Oracle Cloud Infrastructure. *Private* -virtual circuits support private peering, and *public* virtual circuits support -public peering. For more information, see [FastConnect Overview]. - -Each virtual circuit is made up of information shared between a customer, Oracle, -and a provider (if the customer is using FastConnect via a provider). Who fills in -a given property of a virtual circuit depends on whether the BGP session related to -that virtual circuit goes from the customer's edge router to Oracle, or from the provider's -edge router to Oracle. Also, in the case where the customer is using a provider, values -for some of the properties may not be present immediately, but may get filled in as the -provider and Oracle each do their part to provision the virtual circuit. - -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +A virtual circuit is an isolated network path that runs over one or more physical network connections to provide a single, logical connection between the edge router on the customer's existing network and Oracle Cloud Infrastructure. *Private* virtual circuits support private peering, and *public* virtual circuits support public peering. For more information, see [FastConnect Overview]. + +Each virtual circuit is made up of information shared between a customer, Oracle, and a provider (if the customer is using FastConnect via a provider). Who fills in a given property of a virtual circuit depends on whether the BGP session related to that virtual circuit goes from the customer's edge router to Oracle, or from the provider's edge router to Oracle. Also, in the case where the customer is using a provider, values for some of the properties may not be present immediately, but may get filled in as the provider and Oracle each do their part to provision the virtual circuit. + +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def virtual_circuit_group(): pass -@click.command(cli_util.override('local_peering_gateway_group.command_name', 'local-peering-gateway'), cls=CommandGroupWithAlias, help="""A local peering gateway (LPG) is an object on a VCN that lets that VCN peer -with another VCN in the same region. *Peering* means that the two VCNs can -communicate using private IP addresses, but without the traffic traversing the -internet or routing through your on-premises network. For more information, -see [VCN Peering]. +@click.command(cli_util.override('local_peering_gateway_group.command_name', 'local-peering-gateway'), cls=CommandGroupWithAlias, help="""A local peering gateway (LPG) is an object on a VCN that lets that VCN peer with another VCN in the same region. *Peering* means that the two VCNs can communicate using private IP addresses, but without the traffic traversing the internet or routing through your on-premises network. For more information, see [VCN Peering]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def local_peering_gateway_group(): pass @@ -158,69 +108,43 @@ def cross_connect_port_speed_shape_group(): pass -@click.command(cli_util.override('drg_group.command_name', 'drg'), cls=CommandGroupWithAlias, help="""A Dynamic Routing Gateway (DRG), which is a virtual router that provides a path for private -network traffic between your VCN and your existing network. You use it with other Networking -Service components to create an IPSec VPN or a connection that uses -Oracle Cloud Infrastructure FastConnect. For more information, see -[Overview of the Networking Service]. +@click.command(cli_util.override('drg_group.command_name', 'drg'), cls=CommandGroupWithAlias, help="""A Dynamic Routing Gateway (DRG), which is a virtual router that provides a path for private network traffic between your VCN and your existing network. You use it with other Networking Service components to create an IPSec VPN or a connection that uses Oracle Cloud Infrastructure FastConnect. For more information, see [Overview of the Networking Service]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def drg_group(): pass -@click.command(cli_util.override('route_table_group.command_name', 'route-table'), cls=CommandGroupWithAlias, help="""A collection of `RouteRule` objects, which are used to route packets -based on destination IP to a particular network entity. For more information, see -[Overview of the Networking Service]. +@click.command(cli_util.override('route_table_group.command_name', 'route-table'), cls=CommandGroupWithAlias, help="""A collection of `RouteRule` objects, which are used to route packets based on destination IP to a particular network entity. For more information, see [Overview of the Networking Service]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def route_table_group(): pass -@click.command(cli_util.override('cpe_group.command_name', 'cpe'), cls=CommandGroupWithAlias, help="""An object you create when setting up an IPSec VPN between your on-premises network -and VCN. The `Cpe` is a virtual representation of your Customer-Premises Equipment, -which is the actual router on-premises at your site at your end of the IPSec VPN connection. -For more information, -see [Overview of the Networking Service]. +@click.command(cli_util.override('cpe_group.command_name', 'cpe'), cls=CommandGroupWithAlias, help="""An object you create when setting up an IPSec VPN between your on-premises network and VCN. The `Cpe` is a virtual representation of your Customer-Premises Equipment, which is the actual router on-premises at your site at your end of the IPSec VPN connection. For more information, see [Overview of the Networking Service]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def cpe_group(): pass -@click.command(cli_util.override('cross_connect_group.command_name', 'cross-connect'), cls=CommandGroupWithAlias, help="""For use with Oracle Cloud Infrastructure FastConnect. A cross-connect represents a -physical connection between an existing network and Oracle. Customers who are colocated -with Oracle in a FastConnect location create and use cross-connects. For more -information, see [FastConnect Overview]. +@click.command(cli_util.override('cross_connect_group.command_name', 'cross-connect'), cls=CommandGroupWithAlias, help="""For use with Oracle Cloud Infrastructure FastConnect. A cross-connect represents a physical connection between an existing network and Oracle. Customers who are colocated with Oracle in a FastConnect location create and use cross-connects. For more information, see [FastConnect Overview]. -Oracle recommends you create each cross-connect in a -[CrossConnectGroup] so you can use link aggregation -with the connection. +Oracle recommends you create each cross-connect in a [CrossConnectGroup] so you can use link aggregation with the connection. -**Note:** If you're a provider who is setting up a physical connection to Oracle so customers -can use FastConnect over the connection, be aware that your connection is modeled the -same way as a colocated customer's (with `CrossConnect` and `CrossConnectGroup` objects, and so on). +**Note:** If you're a provider who is setting up a physical connection to Oracle so customers can use FastConnect over the connection, be aware that your connection is modeled the same way as a colocated customer's (with `CrossConnect` and `CrossConnectGroup` objects, and so on). -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def cross_connect_group(): pass -@click.command(cli_util.override('letter_of_authority_group.command_name', 'letter-of-authority'), cls=CommandGroupWithAlias, help="""The Letter of Authority for the cross-connect. You must submit this letter when -requesting cabling for the cross-connect at the FastConnect location.""") +@click.command(cli_util.override('letter_of_authority_group.command_name', 'letter-of-authority'), cls=CommandGroupWithAlias, help="""The Letter of Authority for the cross-connect. You must submit this letter when requesting cabling for the cross-connect at the FastConnect location.""") @cli_util.help_option_group def letter_of_authority_group(): pass @@ -232,12 +156,9 @@ def cross_connect_status_group(): pass -@click.command(cli_util.override('vcn_group.command_name', 'vcn'), cls=CommandGroupWithAlias, help="""A Virtual Cloud Network (VCN). For more information, see -[Overview of the Networking Service]. +@click.command(cli_util.override('vcn_group.command_name', 'vcn'), cls=CommandGroupWithAlias, help="""A Virtual Cloud Network (VCN). For more information, see [Overview of the Networking Service]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def vcn_group(): pass @@ -249,41 +170,25 @@ def ip_sec_connection_device_status_group(): pass -@click.command(cli_util.override('vnic_group.command_name', 'vnic'), cls=CommandGroupWithAlias, help="""A virtual network interface card. Each VNIC resides in a subnet in a VCN. -An instance attaches to a VNIC to obtain a network connection into the VCN -through that subnet. Each instance has a *primary VNIC* that is automatically -created and attached during launch. You can add *secondary VNICs* to an -instance after it's launched. For more information, see -[Virtual Network Interface Cards (VNICs)]. +@click.command(cli_util.override('vnic_group.command_name', 'vnic'), cls=CommandGroupWithAlias, help="""A virtual network interface card. Each VNIC resides in a subnet in a VCN. An instance attaches to a VNIC to obtain a network connection into the VCN through that subnet. Each instance has a *primary VNIC* that is automatically created and attached during launch. You can add *secondary VNICs* to an instance after it's launched. For more information, see [Virtual Network Interface Cards (VNICs)]. -Each VNIC has a *primary private IP* that is automatically assigned during launch. -You can add *secondary private IPs* to a VNIC after it's created. For more -information, see [CreatePrivateIp] and -[IP Addresses]. +Each VNIC has a *primary private IP* that is automatically assigned during launch. You can add *secondary private IPs* to a VNIC after it's created. For more information, see [CreatePrivateIp] and [IP Addresses]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def vnic_group(): pass -@click.command(cli_util.override('dhcp_options_group.command_name', 'dhcp-options'), cls=CommandGroupWithAlias, help="""A set of DHCP options. Used by the VCN to automatically provide configuration -information to the instances when they boot up. There are two options you can set: +@click.command(cli_util.override('dhcp_options_group.command_name', 'dhcp-options'), cls=CommandGroupWithAlias, help="""A set of DHCP options. Used by the VCN to automatically provide configuration information to the instances when they boot up. There are two options you can set: -- [DhcpDnsOption]: Lets you specify how DNS (hostname resolution) is -handled in the subnets in your VCN. +- [DhcpDnsOption]: Lets you specify how DNS (hostname resolution) is handled in the subnets in your VCN. -- [DhcpSearchDomainOption]: Lets you specify -a search domain name to use for DNS queries. +- [DhcpSearchDomainOption]: Lets you specify a search domain name to use for DNS queries. -For more information, see [DNS in Your Virtual Cloud Network] -and [DHCP Options]. +For more information, see [DNS in Your Virtual Cloud Network] and [DHCP Options]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def dhcp_options_group(): pass @@ -295,62 +200,37 @@ def virtual_circuit_bandwidth_shape_group(): pass -@click.command(cli_util.override('internet_gateway_group.command_name', 'internet-gateway'), cls=CommandGroupWithAlias, help="""Represents a router that connects the edge of a VCN with the Internet. For an example scenario -that uses an Internet Gateway, see -[Typical Networking Service Scenarios]. +@click.command(cli_util.override('internet_gateway_group.command_name', 'internet-gateway'), cls=CommandGroupWithAlias, help="""Represents a router that connects the edge of a VCN with the Internet. For an example scenario that uses an Internet Gateway, see [Typical Networking Service Scenarios]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def internet_gateway_group(): pass -@click.command(cli_util.override('ip_sec_connection_group.command_name', 'ip-sec-connection'), cls=CommandGroupWithAlias, help="""A connection between a DRG and CPE. This connection consists of multiple IPSec -tunnels. Creating this connection is one of the steps required when setting up -an IPSec VPN. For more information, see -[Overview of the Networking Service]. +@click.command(cli_util.override('ip_sec_connection_group.command_name', 'ip-sec-connection'), cls=CommandGroupWithAlias, help="""A connection between a DRG and CPE. This connection consists of multiple IPSec tunnels. Creating this connection is one of the steps required when setting up an IPSec VPN. For more information, see [Overview of the Networking Service]. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def ip_sec_connection_group(): pass -@click.command(cli_util.override('cross_connect_group_group.command_name', 'cross-connect-group'), cls=CommandGroupWithAlias, help="""For use with Oracle Cloud Infrastructure FastConnect. A cross-connect group -is a link aggregation group (LAG), which can contain one or more -[CrossConnects]. Customers who are colocated with -Oracle in a FastConnect location create and use cross-connect groups. For more -information, see [FastConnect Overview]. +@click.command(cli_util.override('cross_connect_group_group.command_name', 'cross-connect-group'), cls=CommandGroupWithAlias, help="""For use with Oracle Cloud Infrastructure FastConnect. A cross-connect group is a link aggregation group (LAG), which can contain one or more [CrossConnects]. Customers who are colocated with Oracle in a FastConnect location create and use cross-connect groups. For more information, see [FastConnect Overview]. -**Note:** If you're a provider who is setting up a physical connection to Oracle so customers -can use FastConnect over the connection, be aware that your connection is modeled the -same way as a colocated customer's (with `CrossConnect` and `CrossConnectGroup` objects, and so on). +**Note:** If you're a provider who is setting up a physical connection to Oracle so customers can use FastConnect over the connection, be aware that your connection is modeled the same way as a colocated customer's (with `CrossConnect` and `CrossConnectGroup` objects, and so on). -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def cross_connect_group_group(): pass -@click.command(cli_util.override('security_list_group.command_name', 'security-list'), cls=CommandGroupWithAlias, help="""A set of virtual firewall rules for your VCN. Security lists are configured at the subnet -level, but the rules are applied to the ingress and egress traffic for the individual instances -in the subnet. The rules can be stateful or stateless. For more information, see -[Security Lists]. +@click.command(cli_util.override('security_list_group.command_name', 'security-list'), cls=CommandGroupWithAlias, help="""A set of virtual firewall rules for your VCN. Security lists are configured at the subnet level, but the rules are applied to the ingress and egress traffic for the individual instances in the subnet. The rules can be stateful or stateless. For more information, see [Security Lists]. -**Important:** Oracle Cloud Infrastructure Compute service images automatically include firewall rules (for example, -Linux iptables, Windows firewall). If there are issues with some type of access to an instance, -make sure both the security lists associated with the instance's subnet and the instance's -firewall rules are set correctly. +**Important:** Oracle Cloud Infrastructure Compute service images automatically include firewall rules (for example, Linux iptables, Windows firewall). If there are issues with some type of access to an instance, make sure both the security lists associated with the instance's subnet and the instance's firewall rules are set correctly. -To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, -talk to an administrator. If you're an administrator who needs to write policies to give users access, see -[Getting Started with Policies].""") +To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized, talk to an administrator. If you're an administrator who needs to write policies to give users access, see [Getting Started with Policies].""") @cli_util.help_option_group def security_list_group(): pass @@ -1499,6 +1379,18 @@ def delete_cross_connect(ctx, from_json, wait_for_state, max_wait_seconds, wait_ click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_cross_connect, cross_connect_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 Exception 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) @@ -1542,6 +1434,18 @@ def delete_cross_connect_group(ctx, from_json, wait_for_state, max_wait_seconds, click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_cross_connect_group, cross_connect_group_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 Exception 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) @@ -1587,6 +1491,18 @@ def delete_dhcp_options(ctx, from_json, wait_for_state, max_wait_seconds, wait_i click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_dhcp_options, dhcp_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 Exception 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) @@ -1630,6 +1546,18 @@ def delete_drg(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_s click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_drg, drg_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 Exception 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) @@ -1673,6 +1601,18 @@ def delete_drg_attachment(ctx, from_json, wait_for_state, max_wait_seconds, wait click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_drg_attachment, drg_attachment_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 Exception 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) @@ -1718,6 +1658,18 @@ def delete_internet_gateway(ctx, from_json, wait_for_state, max_wait_seconds, wa click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_internet_gateway, ig_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 Exception 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) @@ -1763,6 +1715,18 @@ def delete_ip_sec_connection(ctx, from_json, wait_for_state, max_wait_seconds, w click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_ip_sec_connection, ipsc_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 Exception 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) @@ -1808,6 +1772,18 @@ def delete_local_peering_gateway(ctx, from_json, wait_for_state, max_wait_second click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_local_peering_gateway, local_peering_gateway_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 Exception 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) @@ -1883,6 +1859,18 @@ def delete_public_ip(ctx, from_json, wait_for_state, max_wait_seconds, wait_inte click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_public_ip, public_ip_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 Exception 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) @@ -1928,6 +1916,18 @@ def delete_route_table(ctx, from_json, wait_for_state, max_wait_seconds, wait_in click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_route_table, rt_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 Exception 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) @@ -1973,6 +1973,18 @@ def delete_security_list(ctx, from_json, wait_for_state, max_wait_seconds, wait_ click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_security_list, security_list_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 Exception 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) @@ -2016,6 +2028,18 @@ def delete_subnet(ctx, from_json, wait_for_state, max_wait_seconds, wait_interva click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_subnet, subnet_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 Exception 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) @@ -2059,6 +2083,18 @@ def delete_vcn(ctx, from_json, wait_for_state, max_wait_seconds, wait_interval_s click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_vcn, vcn_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 Exception 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) @@ -2104,6 +2140,18 @@ def delete_virtual_circuit(ctx, from_json, wait_for_state, max_wait_seconds, wai click.echo('Action completed. Waiting until the resource has entered state: {}'.format(wait_for_state), file=sys.stderr) oci.wait_until(client, retry_utils.call_funtion_with_default_retries(client.get_virtual_circuit, virtual_circuit_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 Exception 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) diff --git a/src/oci_cli/object_storage_transfer_manager/transfer_manager.py b/src/oci_cli/object_storage_transfer_manager/transfer_manager.py index 16b5109a6..9fcee8f7f 100644 --- a/src/oci_cli/object_storage_transfer_manager/transfer_manager.py +++ b/src/oci_cli/object_storage_transfer_manager/transfer_manager.py @@ -34,7 +34,14 @@ def __init__(self, object_storage_client, transfer_manager_config): # See: https://laike9m.com/blog/requests-secret-pool_connections-and-pool_maxsize,89/ requests_pool_size = self.REQUESTS_POOL_SIZE_FACTOR * self._config.max_object_storage_requests adapter = requests.adapters.HTTPAdapter(pool_maxsize=requests_pool_size) - self._client.base_client.session.mount('https://', adapter) + + endpoint = object_storage_client.base_client.endpoint.lower() + if endpoint.startswith('https://'): + self._client.base_client.session.mount('https://', adapter) + elif endpoint.startswith('http://'): + self._client.base_client.session.mount('http://', adapter) + else: + raise RuntimeError('Unknown endpoint protocol. Expected HTTP or HTTPS') def upload_object(self, callbacks_container, namespace_name, bucket_name, object_name, file_path, file_size, **kwargs): if not self._config.use_multipart_uploads: diff --git a/src/oci_cli/objectstorage_cli_extended.py b/src/oci_cli/objectstorage_cli_extended.py index 229f8a600..abb38726f 100644 --- a/src/oci_cli/objectstorage_cli_extended.py +++ b/src/oci_cli/objectstorage_cli_extended.py @@ -20,7 +20,7 @@ from .aliasing import CommandGroupWithAlias from .custom_types import BulkPutOperationOutput, BulkGetOperationOutput, BulkDeleteOperationOutput from .generated import objectstorage_cli - +from . import cli_util OBJECT_LIST_PAGE_SIZE = 100 OBJECT_LIST_PAGE_SIZE_BULK_OPERATIONS = 1000 @@ -1298,19 +1298,21 @@ def object_resume_put(ctx, from_json, namespace, bucket_name, name, file, upload render(None, display_headers, ctx, display_all_headers=True) -@objectstorage_cli.object_group.command(name='restore', help="""Restore an object by specifying the name parameter.""") +@cli_util.copy_params_from_generated_command(objectstorage_cli.restore_objects, params_to_exclude=['namespace_name', 'bucket_name', 'object_name']) +@objectstorage_cli.object_group.command(name='restore', help=objectstorage_cli.restore_objects.help) @click.option('-ns', '--namespace', callback=handle_required_param, help="""The top-level namespace used for the request. [required]""") @click.option('-bn', '--bucket', callback=handle_required_param, help="""The name of the bucket. Avoid entering confidential information. Example: `my-new-bucket1` [required]""") @click.option('--name', callback=handle_required_param, help="""A object which was in an archived state and need to be restored. [required]""") -@json_skeleton_utils.get_cli_json_input_option({}) -@help_option @click.pass_context @json_skeleton_utils.json_skeleton_generation_handler(input_params_to_complex_types={}) @wrap_exceptions -def restore_objects(ctx, from_json, namespace, bucket, name): +def restore_objects(ctx, from_json, namespace, bucket, name, hours): details = {} details['objectName'] = name + if hours is not None: + details['hours'] = hours + client = build_client('object_storage', ctx) kwargs = {'opc_client_request_id': ctx.obj['request_id']} result = client.restore_objects( @@ -1363,9 +1365,9 @@ def restore_status(ctx, from_json, namespace, bucket_name, name): time_of_archival = response.headers['time-of-archival'] time_of_archival_dt = arrow.get(time_of_archival, 'YYYY-MM-DDTHH:mm:ss.SSS[Z]') time_left = time_delta((time_of_archival_dt - arrow.utcnow()).seconds) - msg = "Restored, you have 24 hours to download a restored object before it is once again archived. Time remaining for download: {}.".format(time_left) + msg = "Restored. You have {} to download the restored object before it is once again archived.".format(time_left) except arrow.parser.ParserError: - msg = "Restored, you have 24 hours to download a restored object before it is once again archived. The object will be re-archived at {}.".format(time_of_archival) + msg = "Restored. The object will be re-archived at {}.".format(time_of_archival) else: msg = "Unknown" diff --git a/src/oci_cli/version.py b/src/oci_cli/version.py index 9dca0d002..eb4f469b9 100644 --- a/src/oci_cli/version.py +++ b/src/oci_cli/version.py @@ -1,4 +1,4 @@ # coding: utf-8 # Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. -__version__ = '2.4.16' +__version__ = '2.4.17' diff --git a/tests/__init__.py b/tests/__init__.py index ab8b5307d..959b3b136 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,2 +1,4 @@ # coding: utf-8 # Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + +# noqa: W391, W292 \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index 4fe144246..7054dfa98 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -107,6 +107,11 @@ def compute_client(config): return oci.core.ComputeClient(config) +@pytest.fixture(scope='session') +def filestorage_client(config): + return oci.file_storage.FileStorageClient(config) + + @pytest.fixture(scope='session') def identity_client(config): return oci.identity.IdentityClient(config) diff --git a/tests/output/inline_help_dump.txt b/tests/output/inline_help_dump.txt index e5554837c..2e977906f 100644 --- a/tests/output/inline_help_dump.txt +++ b/tests/output/inline_help_dump.txt @@ -1,4 +1,4 @@ -This file contains all the help for every possible command in version 2.4.16 of the CLI. +This file contains all the help for every possible command in version 2.4.17 of the CLI. This file is generated by running test_help.py, which dumps the output of --help for every command. @@ -101,6 +101,7 @@ Commands: compute Compute Service db Database Service dns API for managing DNS zones, records, and... + fs File Storage Service iam Identity and Access Management Service lb Load Balancing Service network Networking Service @@ -2545,8 +2546,8 @@ $ oci compute instance attach-vnic --help Usage: oci compute instance attach-vnic [OPTIONS] Creates a secondary VNIC and attaches it to the specified instance. For more - information about secondary VNICs, see [Managing Virtual Network Interface - Cards (VNICs)]. + information about secondary VNICs, see [Virtual Network Interface Cards + (VNICs)]. Options: --instance-id TEXT The OCID of the instance. [required] @@ -2811,7 +2812,7 @@ Options: Must be unique across all VNICs in the subnet and comply with [RFC 952] and [RFC 1123]. The value cannot be changed, and it can be - retrieved from the [Vnic object]. + retrieved from the [Vnic]. For more information, see [DNS in Your Virtual Cloud @@ -3096,7 +3097,7 @@ Options: the resource's current etag value. --preserve-boot-volume BOOLEAN Specifies whether to delete or preserve the boot volume when terminating an instance. The - default value is false. Defaults to true. + default value is false. --force Perform deletion without prompting for confirmation. --wait-for-state [PROVISIONING|RUNNING|STARTING|STOPPING|STOPPED|CREATING_IMAGE|TERMINATING|TERMINATED] @@ -3222,14 +3223,21 @@ Usage: oci compute instance-console-connection [OPTIONS] COMMAND [ARGS]... For more information about console access, see [Accessing the Console]. + If you are attempting to start a VNC connection to an instance from a + Windows machine without SSH installed, you can consider using plink instead. + The 'oci compute instance-console-connection get-plink-connection-string' + command returns a PowerShell command which uses plink to launch the SSH + tunnel necessary to start a VNC connection to the instance. + Options: -?, -h, --help Show this message and exit. Commands: - create Creates a new serial console connection to... - delete Deletes the specified instance console... - get Gets the specified instance console... - list Lists the console connections for the... + create Creates a new serial console connection to... + delete Deletes the specified instance console... + get Gets the specified instance console... + get-plink-connection-string Gets the plink command for starting an SSH... + list Lists the console connections for the... ++++++++++++++++++++++++++++++++++++++++++++++ $ oci compute instance-console-connection create --help @@ -3241,8 +3249,8 @@ Usage: oci compute instance-console-connection create [OPTIONS] The default number of enabled serial console connections per tenancy is 10. - For more information about serial console access, see [Accessing the Serial - Console]. + For more information about serial console access, see [Accessing the + Instance Console]. Options: --instance-id TEXT The OCID of the instance to create the console @@ -3364,10 +3372,51 @@ Usage: oci compute instance-console-connection get [OPTIONS] Gets the specified instance console connection's information. + If you are attempting to start a VNC connection to an instance from a + Windows machine without SSH installed, you can consider using plink instead. + The 'oci compute instance-console-connection get-plink-connection-string' + command returns a PowerShell command which uses plink to launch the SSH + tunnel necessary to start a VNC connection to the instance. + +Options: + --instance-console-connection-id TEXT + The OCID of the intance console connection + [required] + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci compute instance-console-connection get-plink-connection-string --help +Usage: oci compute instance-console-connection get-plink-connection-string + [OPTIONS] + + Gets the plink command for starting an SSH tunnel on Windows which will + allow VNC connections to the instance. Once you have started the tunnel, you + can point your VNC client to localhost:{--local-vnc-port} to connect to the + instance (default --local-vnc-port is 5900). + Options: --instance-console-connection-id TEXT The OCID of the intance console connection [required] + --private-key-file TEXT The path to the private key to be used for + authentication. This is inserted into the + generated connection string. + --local-vnc-port TEXT This is the local port that you will point + your VNC client at. This will be forwarded to + the SSH tunnel created by executing the + PowerShell command in the output. Default is + 5900. + --ssh-proxy-port TEXT This is the local and remote port for the SSH + tunnel. This may be any open port on your + local machine. Default is 5905. --from-json TEXT Provide input to this command as a JSON document from a file. @@ -5164,12 +5213,17 @@ Options: $ oci db system list --help Usage: oci db system list [OPTIONS] - Gets a list of the DB Systems in the specified compartment. + Gets a list of the DB Systems in the specified compartment. You can specify + a backupId to list only the DB Systems that support creating a database + using this backup in this compartment. Options: -c, --compartment-id TEXT The compartment [OCID]. [required] --limit INTEGER The maximum number of items to return. --page TEXT The pagination token to continue listing from. + --backup-id TEXT The OCID of the backup. Specify a backupId to list + only the DB Systems that support creating a + database using this backup in this compartment. --all Fetches all pages of results. If you provide this option, then you cannot provide the --limit option. --page-size INTEGER When fetching results, the number of results to @@ -6319,6 +6373,1034 @@ Options: value will be used -?, -h, --help Show this message and exit. +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs --help +Usage: oci fs [OPTIONS] COMMAND [ARGS]... + + File Storage Service + +Options: + -?, -h, --help Show this message and exit. + +Commands: + export A file system and the path that you can use... + export-set A set of file systems to export through one... + file-system An NFS file system. + mount-target Provides access to a collection of file... + snapshot A point-in-time snapshot of a specified file... + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs export --help +Usage: oci fs export [OPTIONS] COMMAND [ARGS]... + + A file system and the path that you can use to mount it. Each export + resource belongs to exactly one export set. + + The export's path attribute is not a path in the referenced file system, but + the value used by clients for the path component of the remotetarget + argument when mounting the file system. + + The path must start with a slash (/) followed by a sequence of zero or more + slash-separated path elements. For any two export resources associated with + the same export set, except those in a 'DELETED' state, the path element + sequence for the first export resource can't contain the complete path + element sequence of the second export resource. + + For example, the following are acceptable: + + * /foo and /bar * /foo1 and /foo2 * /foo and /foo1 + + The following examples are not acceptable: * /foo and /foo/bar * / and + /foo + + Paths may not end in a slash (/). No path element can be a period (.) or two + periods in sequence (..). All path elements must be 255 bytes or less. + + No two non-'DELETED' export resources in the same export set can reference + the same file system. + +Options: + -?, -h, --help Show this message and exit. + +Commands: + create Creates a new export in the specified export... + delete Deletes the specified export. + get Gets the specified export's information. + list Lists the export resources in the specified... + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs export create --help +Usage: oci fs export create [OPTIONS] + + Creates a new export in the specified export set, path, and file system. + +Options: + --export-set-id TEXT The OCID of this export's export set. + [required] + --file-system-id TEXT The OCID of this export's file system. + [required] + --path TEXT Path used to access the associated file + system. + + Avoid entering confidential + information. + + Example: `/mediafiles` + [required] + --wait-for-state [CREATING|ACTIVE|DELETING|DELETED] + 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. + --max-wait-seconds INTEGER The maximum time to wait for the resource to + reach the lifecycle state defined by --wait- + for-state. Defaults to 1200 seconds. + --wait-interval-seconds INTEGER + Check every --wait-interval-seconds to see + whether the resource to see if it has reached + the lifecycle state defined by --wait-for- + state. Defaults to 30 seconds. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs export delete --help +Usage: oci fs export delete [OPTIONS] + + Deletes the specified export. + +Options: + --export-id TEXT The OCID of the export. [required] + --if-match TEXT 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. + --force Perform deletion without prompting for + confirmation. + --wait-for-state [CREATING|ACTIVE|DELETING|DELETED] + 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. + --max-wait-seconds INTEGER The maximum time to wait for the resource to + reach the lifecycle state defined by --wait- + for-state. Defaults to 1200 seconds. + --wait-interval-seconds INTEGER + Check every --wait-interval-seconds to see + whether the resource to see if it has reached + the lifecycle state defined by --wait-for- + state. Defaults to 30 seconds. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs export get --help +Usage: oci fs export get [OPTIONS] + + Gets the specified export's information. + +Options: + --export-id TEXT The OCID of the export. [required] + --from-json TEXT Provide input to this command as a JSON document from a + file. + + Options can still be provided on the command line. If + an option exists in both the JSON document and the command + line then the command line specified value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs export list --help +Usage: oci fs export list [OPTIONS] + + Lists the export resources in the specified compartment. You must also + specify an export set, a file system, or both. + +Options: + -c, --compartment-id TEXT The OCID of the compartment. [required] + --limit INTEGER The maximum number of items to return in a + paginated "List" call. + + Example: `500` + --page TEXT The value of the `opc-next-page` response + header from the previous "List" call. + --export-set-id TEXT The OCID of the export set. + --file-system-id TEXT The OCID of the file system. + --lifecycle-state [CREATING|ACTIVE|DELETING|DELETED|FAILED] + Filter results by the specified lifecycle + state. Must be a valid state for the resource + type. + --id TEXT Filter results by OCID. Must be an OCID of the + correct type for the resouce type. + --sort-by [TIMECREATED|PATH] The field to sort by. You can provide either + value, but not both. By default, when you sort + by time created, results are shown in + descending order. When you sort by path, + results are shown in ascending alphanumeric + order. + --sort-order [ASC|DESC] The sort order to use, either 'asc' or 'desc', + where 'asc' is ascending and 'desc' is + descending. + --all Fetches all pages of results. If you provide + this option, then you cannot provide the + --limit option. + --page-size INTEGER When fetching results, the number of results + to fetch per call. Only valid when used with + --all or --limit, and ignored otherwise. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs export-set --help +Usage: oci fs export-set [OPTIONS] COMMAND [ARGS]... + + A set of file systems to export through one or more mount targets. Composed + of zero or more export resources. + +Options: + -?, -h, --help Show this message and exit. + +Commands: + get Gets the specified export set's information. + list Lists the export set resources in the... + update Updates the specified export set's... + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs export-set get --help +Usage: oci fs export-set get [OPTIONS] + + Gets the specified export set's information. + +Options: + --export-set-id TEXT The OCID of the export set. [required] + --from-json TEXT Provide input to this command as a JSON document from a + file. + + Options can still be provided on the command + line. If an option exists in both the JSON document and + the command line then the command line specified value + will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs export-set list --help +Usage: oci fs export-set list [OPTIONS] + + Lists the export set resources in the specified compartment. + +Options: + -c, --compartment-id TEXT The OCID of the compartment. [required] + --availability-domain TEXT The name of the availability domain. + + Example: + `Uocm:PHX-AD-1` [required] + --limit INTEGER The maximum number of items to return in a + paginated "List" call. + + Example: `500` + --page TEXT The value of the `opc-next-page` response + header from the previous "List" call. + --display-name TEXT A user-friendly name. It does not have to be + unique, and it is changeable. + + Example: `My + resource` + --lifecycle-state [CREATING|ACTIVE|DELETING|DELETED|FAILED] + Filter results by the specified lifecycle + state. Must be a valid state for the resource + type. + --id TEXT Filter results by OCID. Must be an OCID of the + correct type for the resouce type. + --sort-by [TIMECREATED|DISPLAYNAME] + The field to sort by. You can provide either + value, but not both. By default, when you sort + by time created, results are shown in + descending order. When you sort by display + name, results are shown in ascending order. + --sort-order [ASC|DESC] The sort order to use, either 'asc' or 'desc', + where 'asc' is ascending and 'desc' is + descending. + --all Fetches all pages of results. If you provide + this option, then you cannot provide the + --limit option. + --page-size INTEGER When fetching results, the number of results + to fetch per call. Only valid when used with + --all or --limit, and ignored otherwise. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs export-set update --help +Usage: oci fs export-set update [OPTIONS] + + Updates the specified export set's information. + +Options: + --export-set-id TEXT The OCID of the export set. [required] + --display-name TEXT A user-friendly name. It does not have to be + unique, and it is changeable. Avoid entering + confidential information. + + Example: `My export + set` + --max-fs-stat-bytes INTEGER Controls the maximum `tbytes`, `fbytes`, and + `abytes` values reported by `NFS FSSTAT` calls + through any associated mount targets. This is + an advanced feature. For most applications, + use the default value. The `tbytes` value + reported by `FSSTAT` will be `maxFsStatBytes`. + The value of `fbytes` and `abytes` will be + `maxFsStatBytes` minus the metered size of the + file system. If the metered size is larger + than `maxFsStatBytes`, then `fbytes` and + `abytes` will both be '0'. + --max-fs-stat-files INTEGER Controls the maximum `ffiles`, `ffiles`, and + `afiles` values reported by `NFS FSSTAT` calls + through any associated mount targets. This is + an advanced feature. For most applications, + use the default value. The `tfiles` value + reported by `FSSTAT` will be `maxFsStatFiles`. + The value of `ffiles` and `afiles` will be + `maxFsStatFiles` minus the metered size of the + file system. If the metered size is larger + than `maxFsStatFiles`, then `ffiles` and + `afiles` will both be '0'. + --if-match TEXT 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. + --wait-for-state [CREATING|ACTIVE|DELETING|DELETED] + 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. + --max-wait-seconds INTEGER The maximum time to wait for the resource to + reach the lifecycle state defined by --wait- + for-state. Defaults to 1200 seconds. + --wait-interval-seconds INTEGER + Check every --wait-interval-seconds to see + whether the resource to see if it has reached + the lifecycle state defined by --wait-for- + state. Defaults to 30 seconds. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs file-system --help +Usage: oci fs file-system [OPTIONS] COMMAND [ARGS]... + + An NFS file system. To allow access to a file system, add it to an export + set and associate the export set with a mount target. The same file system + can be in multiple export sets and associated with multiple mount targets. + + To use any of the API operations, you must be authorized in an IAM policy. + If you're not authorized, talk to an administrator. If you're an + administrator who needs to write policies to give users access, see [Getting + Started with Policies]. + +Options: + -?, -h, --help Show this message and exit. + +Commands: + create Creates a new file system in the specified... + delete Deletes the specified file system. + get Gets the specified file system's information. + list Lists the file system resources in the... + update Updates the specified file system's... + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs file-system create --help +Usage: oci fs file-system create [OPTIONS] + + Creates a new file system in the specified compartment and availability + domain. Instances can mount file systems in another availability domain, but + doing so might increase latency when compared to mounting instances in the + same availability domain. + + After you create a file system, you can associate it with a mount target. + Instances can then mount the file system by connecting to the mount target's + IP address. You can associate a file system with more than one mount target + at a time. + + For information about access control and compartments, see [Overview of the + IAM Service]. + + For information about availability domains, see [Regions and Availability + Domains]. To get a list of availability domains, use the + `ListAvailabilityDomains` operation in the Identity and Access Management + Service API. + + All Oracle Cloud Infrastructure resources, including file systems, get an + Oracle-assigned, unique ID called an Oracle Cloud Identifier (OCID). When + you create a resource, you can find its OCID in the response. You can also + retrieve a resource's OCID by using a List API operation on that resource + type or by viewing the resource in the Console. + +Options: + --availability-domain TEXT The availability domain to create the file + system in. + + Example: `Uocm:PHX-AD-1` + [required] + -c, --compartment-id TEXT The OCID of the compartment to create the file + system in. [required] + --display-name TEXT A user-friendly name. It does not have to be + unique, and it is changeable. Avoid entering + confidential information. + + Example: `My file + system` + --wait-for-state [CREATING|ACTIVE|DELETING|DELETED] + 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. + --max-wait-seconds INTEGER The maximum time to wait for the resource to + reach the lifecycle state defined by --wait- + for-state. Defaults to 1200 seconds. + --wait-interval-seconds INTEGER + Check every --wait-interval-seconds to see + whether the resource to see if it has reached + the lifecycle state defined by --wait-for- + state. Defaults to 30 seconds. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs file-system delete --help +Usage: oci fs file-system delete [OPTIONS] + + Deletes the specified file system. Before you delete the file system, verify + that no remaining export resources still reference it. Deleting a file + system also deletes all of its snapshots. + +Options: + --file-system-id TEXT The OCID of the file system. [required] + --if-match TEXT 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. + --force Perform deletion without prompting for + confirmation. + --wait-for-state [CREATING|ACTIVE|DELETING|DELETED] + 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. + --max-wait-seconds INTEGER The maximum time to wait for the resource to + reach the lifecycle state defined by --wait- + for-state. Defaults to 1200 seconds. + --wait-interval-seconds INTEGER + Check every --wait-interval-seconds to see + whether the resource to see if it has reached + the lifecycle state defined by --wait-for- + state. Defaults to 30 seconds. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs file-system get --help +Usage: oci fs file-system get [OPTIONS] + + Gets the specified file system's information. + +Options: + --file-system-id TEXT The OCID of the file system. [required] + --from-json TEXT Provide input to this command as a JSON document from a + file. + + Options can still be provided on the command + line. If an option exists in both the JSON document and + the command line then the command line specified value + will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs file-system list --help +Usage: oci fs file-system list [OPTIONS] + + Lists the file system resources in the specified compartment. + +Options: + -c, --compartment-id TEXT The OCID of the compartment. [required] + --availability-domain TEXT The name of the availability domain. + + Example: + `Uocm:PHX-AD-1` [required] + --limit INTEGER The maximum number of items to return in a + paginated "List" call. + + Example: `500` + --page TEXT The value of the `opc-next-page` response + header from the previous "List" call. + --display-name TEXT A user-friendly name. It does not have to be + unique, and it is changeable. + + Example: `My + resource` + --lifecycle-state [CREATING|ACTIVE|DELETING|DELETED|FAILED] + Filter results by the specified lifecycle + state. Must be a valid state for the resource + type. + --id TEXT Filter results by OCID. Must be an OCID of the + correct type for the resouce type. + --sort-by [TIMECREATED|DISPLAYNAME] + The field to sort by. You can provide either + value, but not both. By default, when you sort + by time created, results are shown in + descending order. When you sort by display + name, results are shown in ascending order. + --sort-order [ASC|DESC] The sort order to use, either 'asc' or 'desc', + where 'asc' is ascending and 'desc' is + descending. + --all Fetches all pages of results. If you provide + this option, then you cannot provide the + --limit option. + --page-size INTEGER When fetching results, the number of results + to fetch per call. Only valid when used with + --all or --limit, and ignored otherwise. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs file-system update --help +Usage: oci fs file-system update [OPTIONS] + + Updates the specified file system's information. You can use this operation + to rename a file system. + +Options: + --file-system-id TEXT The OCID of the file system. [required] + --display-name TEXT A user-friendly name. It does not have to be + unique, and it is changeable. Avoid entering + confidential information. + + Example: `My file + system` + --if-match TEXT 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. + --wait-for-state [CREATING|ACTIVE|DELETING|DELETED] + 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. + --max-wait-seconds INTEGER The maximum time to wait for the resource to + reach the lifecycle state defined by --wait- + for-state. Defaults to 1200 seconds. + --wait-interval-seconds INTEGER + Check every --wait-interval-seconds to see + whether the resource to see if it has reached + the lifecycle state defined by --wait-for- + state. Defaults to 30 seconds. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs mount-target --help +Usage: oci fs mount-target [OPTIONS] COMMAND [ARGS]... + + Provides access to a collection of file systems through one or more VNICs on + a specified subnet. The set of file systems is controlled through the + referenced export set. + +Options: + -?, -h, --help Show this message and exit. + +Commands: + create Creates a new mount target in the specified... + delete Deletes the specified mount target. + get Gets the specified mount target's... + list Lists the mount target resources in the... + update Updates the specified mount target's... + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs mount-target create --help +Usage: oci fs mount-target create [OPTIONS] + + Creates a new mount target in the specified compartment and subnet. You can + associate a file system with a mount target only when they exist in the same + availability domain. Instances can connect to mount targets in another + availablity domain, but you might see higher latency than with instances in + the same availability domain as the mount target. + + Mount targets have one or more private IP addresses that you can provide as + the host portion of remote target parameters in client mount commands. These + private IP addresses are listed in the privateIpIds property of the mount + target and are highly available. Mount targets also consume additional IP + addresses in their subnet. + + For information about access control and compartments, see [Overview of the + IAM Service]. + + For information about availability domains, see [Regions and Availability + Domains]. To get a list of availability domains, use the + `ListAvailabilityDomains` operation in the Identity and Access Management + Service API. + + All Oracle Cloud Infrastructure Services resources, including mount targets, + get an Oracle-assigned, unique ID called an Oracle Cloud Identifier (OCID). + When you create a resource, you can find its OCID in the response. You can + also retrieve a resource's OCID by using a List API operation on that + resource type, or by viewing the resource in the Console. + +Options: + --availability-domain TEXT The availability domain in which to create the + mount target. + + Example: `Uocm:PHX-AD-1` + [required] + -c, --compartment-id TEXT The OCID of the compartment in which to create + the mount target. [required] + --subnet-id TEXT The OCID of the subnet in which to create the + mount target. [required] + --display-name TEXT A user-friendly name. It does not have to be + unique, and it is changeable. Avoid entering + confidential information. + + Example: `My mount + target` + --hostname-label TEXT The hostname for the mount target's IP + address, used for DNS resolution. The value is + the hostname portion of the private IP + address's fully qualified domain name (FQDN). + For example, `files-1` in the FQDN + `files-1.subnet123.vcn1.oraclevcn.com`. Must + be unique across all VNICs in the subnet and + comply with [RFC 952] and [RFC 1123]. + + For + more information, see [DNS in Your Virtual + Cloud Network]. + + Example: `files-1` + --ip-address TEXT A private IP address of your choice. 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. + + Example: `10.0.3.3` + --wait-for-state [CREATING|ACTIVE|DELETING|DELETED|FAILED] + 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. + --max-wait-seconds INTEGER The maximum time to wait for the resource to + reach the lifecycle state defined by --wait- + for-state. Defaults to 1200 seconds. + --wait-interval-seconds INTEGER + Check every --wait-interval-seconds to see + whether the resource to see if it has reached + the lifecycle state defined by --wait-for- + state. Defaults to 30 seconds. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs mount-target delete --help +Usage: oci fs mount-target delete [OPTIONS] + + Deletes the specified mount target. This operation also deletes the mount + target's VNICs. + +Options: + --mount-target-id TEXT The OCID of the mount target. [required] + --if-match TEXT 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. + --force Perform deletion without prompting for + confirmation. + --wait-for-state [CREATING|ACTIVE|DELETING|DELETED|FAILED] + 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. + --max-wait-seconds INTEGER The maximum time to wait for the resource to + reach the lifecycle state defined by --wait- + for-state. Defaults to 1200 seconds. + --wait-interval-seconds INTEGER + Check every --wait-interval-seconds to see + whether the resource to see if it has reached + the lifecycle state defined by --wait-for- + state. Defaults to 30 seconds. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs mount-target get --help +Usage: oci fs mount-target get [OPTIONS] + + Gets the specified mount target's information. + +Options: + --mount-target-id TEXT The OCID of the mount target. [required] + --from-json TEXT Provide input to this command as a JSON document from + a file. + + Options can still be provided on the command + line. If an option exists in both the JSON document + and the command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs mount-target list --help +Usage: oci fs mount-target list [OPTIONS] + + Lists the mount target resources in the specified compartment. + +Options: + -c, --compartment-id TEXT The OCID of the compartment. [required] + --availability-domain TEXT The name of the availability domain. + + Example: + `Uocm:PHX-AD-1` [required] + --limit INTEGER The maximum number of items to return in a + paginated "List" call. + + Example: `500` + --page TEXT The value of the `opc-next-page` response + header from the previous "List" call. + --display-name TEXT A user-friendly name. It does not have to be + unique, and it is changeable. + + Example: `My + resource` + --export-set-id TEXT The OCID of the export set. + --lifecycle-state [CREATING|ACTIVE|DELETING|DELETED|FAILED] + Filter results by the specified lifecycle + state. Must be a valid state for the resource + type. + --id TEXT Filter results by OCID. Must be an OCID of the + correct type for the resouce type. + --sort-by [TIMECREATED|DISPLAYNAME] + The field to sort by. You can choose either + value, but not both. By default, when you sort + by time created, results are shown in + descending order. When you sort by display + name, results are shown in ascending order. + --sort-order [ASC|DESC] The sort order to use, either 'asc' or 'desc', + where 'asc' is ascending and 'desc' is + descending. + --all Fetches all pages of results. If you provide + this option, then you cannot provide the + --limit option. + --page-size INTEGER When fetching results, the number of results + to fetch per call. Only valid when used with + --all or --limit, and ignored otherwise. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs mount-target update --help +Usage: oci fs mount-target update [OPTIONS] + + Updates the specified mount target's information. + +Options: + --mount-target-id TEXT The OCID of the mount target. [required] + --display-name TEXT A user-friendly name. Does not have to be + unique, and it is changeable. Avoid entering + confidential information. + + Example: `My mount + target` + --if-match TEXT 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. + --wait-for-state [CREATING|ACTIVE|DELETING|DELETED|FAILED] + 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. + --max-wait-seconds INTEGER The maximum time to wait for the resource to + reach the lifecycle state defined by --wait- + for-state. Defaults to 1200 seconds. + --wait-interval-seconds INTEGER + Check every --wait-interval-seconds to see + whether the resource to see if it has reached + the lifecycle state defined by --wait-for- + state. Defaults to 30 seconds. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs snapshot --help +Usage: oci fs snapshot [OPTIONS] COMMAND [ARGS]... + + A point-in-time snapshot of a specified file system. + +Options: + -?, -h, --help Show this message and exit. + +Commands: + create Creates a new snapshot of the specified file... + delete Deletes the specified snapshot. + get Gets the specified snapshot's information. + list Lists snapshots of the specified file system. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs snapshot create --help +Usage: oci fs snapshot create [OPTIONS] + + Creates a new snapshot of the specified file system. You can access the + snapshot at `.snapshot/`. + +Options: + --file-system-id TEXT The OCID of this export's file system. + [required] + --name TEXT Name of the snapshot. This value is immutable. + It must also be unique with respect to all + other non-DELETED snapshots on the associated + file system. + + Avoid entering confidential + information. + + Example: `Sunday` [required] + --wait-for-state [CREATING|ACTIVE|DELETING|DELETED] + 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. + --max-wait-seconds INTEGER The maximum time to wait for the resource to + reach the lifecycle state defined by --wait- + for-state. Defaults to 1200 seconds. + --wait-interval-seconds INTEGER + Check every --wait-interval-seconds to see + whether the resource to see if it has reached + the lifecycle state defined by --wait-for- + state. Defaults to 30 seconds. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs snapshot delete --help +Usage: oci fs snapshot delete [OPTIONS] + + Deletes the specified snapshot. + +Options: + --snapshot-id TEXT The OCID of the snapshot. [required] + --if-match TEXT 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. + --force Perform deletion without prompting for + confirmation. + --wait-for-state [CREATING|ACTIVE|DELETING|DELETED] + 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. + --max-wait-seconds INTEGER The maximum time to wait for the resource to + reach the lifecycle state defined by --wait- + for-state. Defaults to 1200 seconds. + --wait-interval-seconds INTEGER + Check every --wait-interval-seconds to see + whether the resource to see if it has reached + the lifecycle state defined by --wait-for- + state. Defaults to 30 seconds. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs snapshot get --help +Usage: oci fs snapshot get [OPTIONS] + + Gets the specified snapshot's information. + +Options: + --snapshot-id TEXT The OCID of the snapshot. [required] + --from-json TEXT Provide input to this command as a JSON document from a + file. + + Options can still be provided on the command line. + If an option exists in both the JSON document and the + command line then the command line specified value will be + used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci fs snapshot list --help +Usage: oci fs snapshot list [OPTIONS] + + Lists snapshots of the specified file system. + +Options: + --file-system-id TEXT The OCID of the file system. [required] + --limit INTEGER The maximum number of items to return in a + paginated "List" call. + + Example: `500` + --page TEXT The value of the `opc-next-page` response + header from the previous "List" call. + --lifecycle-state [CREATING|ACTIVE|DELETING|DELETED|FAILED] + Filter results by the specified lifecycle + state. Must be a valid state for the resource + type. + --id TEXT Filter results by OCID. Must be an OCID of the + correct type for the resouce type. + --sort-order [ASC|DESC] The sort order to use, either 'asc' or 'desc', + where 'asc' is ascending and 'desc' is + descending. + --all Fetches all pages of results. If you provide + this option, then you cannot provide the + --limit option. + --page-size INTEGER When fetching results, the number of results + to fetch per call. Only valid when used with + --all or --limit, and ignored otherwise. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + ++++++++++++++++++++++++++++++++++++++++++++++ $ oci iam --help Usage: oci iam [OPTIONS] COMMAND [ARGS]... @@ -8938,6 +10020,7 @@ Commands: listener The listener's configuration. load-balancer The properties that define a load balancer. load-balancer-health The health status details for the specified... + path-route-set A named set of path route rules. policy A policy that determines how traffic is... protocol The protocol that defines the type of traffic... shape A shape is a template that determines the... @@ -9937,6 +11020,12 @@ Options: Example: `HTTP` [required] --load-balancer-id TEXT The [OCID] of the load balancer on which to add a listener. [required] + --path-route-set-name TEXT The name of the set of path-based routing + rules, [PathRouteSet], applied to this + listener's traffic. + + Example: `path-route- + set-001` --wait-for-state [ACCEPTED|IN_PROGRESS|FAILED|SUCCEEDED] This operation asynchronously creates, modifies or deletes a resource and uses a work @@ -10050,6 +11139,12 @@ Options: Example: `My listener` [required] + --path-route-set-name TEXT The name of the set of path-based routing + rules, [PathRouteSet], applied to this + listener's traffic. + + Example: `path-route- + set-001` --force Perform update without prompting for confirmation. --wait-for-state [ACCEPTED|IN_PROGRESS|FAILED|SUCCEEDED] @@ -10278,6 +11373,25 @@ Options: the file://path/to/file syntax. + The --generate- + param-json-input option can be used to + generate an example of the JSON which must be + provided. We recommend storing this example + in + a file, modifying it as needed and then + passing it back in via the file:// syntax. + --path-route-sets COMPLEX TYPE This option is a JSON dictionary of type + dict(str, PathRouteSetDetails). For + documentation on PathRouteSetDetails please + see our API reference: https://docs.us- + phoenix-1.oraclecloud.com/api/#. + This is a + complex type whose value must be valid JSON. + The value can be provided as a string on the + command line or passed in as a file using + the + file://path/to/file syntax. + The --generate- param-json-input option can be used to generate an example of the JSON which must be @@ -10481,6 +11595,213 @@ Options: specified value will be used -?, -h, --help Show this message and exit. +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci lb path-route-set --help +Usage: oci lb path-route-set [OPTIONS] COMMAND [ARGS]... + + A named set of path route rules. For more information, see [Managing Request + Routing]. + +Options: + -?, -h, --help Show this message and exit. + +Commands: + create Adds a path route set to a load balancer. + delete Deletes a path route set from the specified... + get Gets the specified path route set's... + list Lists all path route sets associated with the... + update Overwrites an existing path route set on the... + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci lb path-route-set create --help +Usage: oci lb path-route-set create [OPTIONS] + + Adds a path route set to a load balancer. For more information, see + [Managing Request Routing]. + +Options: + --name TEXT The name for this set of path route rules. It + must be unique and it cannot be changed. Avoid + entering confidential information. + + Example: + `path-route-set-001` [required] + --path-routes COMPLEX TYPE The set of path route rules. [required] + This + is a complex type whose value must be valid + JSON. The value can be provided as a string on + the command line or passed in as a file using + the file://path/to/file syntax. + + The + --generate-param-json-input option can be used + to generate an example of the JSON which must + be provided. We recommend storing this example + in a file, modifying it as needed and then + passing it back in via the file:// syntax. + --load-balancer-id TEXT The [OCID] of the load balancer to add the + path route set to. [required] + --wait-for-state [ACCEPTED|IN_PROGRESS|FAILED|SUCCEEDED] + 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. + --max-wait-seconds INTEGER The maximum time to wait for the work request + to reach the state defined by --wait-for- + state. Defaults to 1200 seconds. + --wait-interval-seconds INTEGER + 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. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci lb path-route-set delete --help +Usage: oci lb path-route-set delete [OPTIONS] + + Deletes a path route set from the specified load balancer. + + To delete a path route rule from a path route set, use the + [UpdatePathRouteSet] operation. + +Options: + --load-balancer-id TEXT The [OCID] of the load balancer associated + with the path route set to delete. [required] + --path-route-set-name TEXT The name of the path route set to delete. + Example: `path-route-set-001` [required] + --force Perform deletion without prompting for + confirmation. + --wait-for-state [ACCEPTED|IN_PROGRESS|FAILED|SUCCEEDED] + 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. + --max-wait-seconds INTEGER The maximum time to wait for the work request + to reach the state defined by --wait-for- + state. Defaults to 1200 seconds. + --wait-interval-seconds INTEGER + 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. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci lb path-route-set get --help +Usage: oci lb path-route-set get [OPTIONS] + + Gets the specified path route set's configuration information. + +Options: + --load-balancer-id TEXT The [OCID] of the specified load balancer. + [required] + --path-route-set-name TEXT The name of the path route set to retrieve. + Example: `path-route-set-001` [required] + --from-json TEXT Provide input to this command as a JSON document + from a file. + + Options can still be provided on the + command line. If an option exists in both the JSON + document and the command line then the command + line specified value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci lb path-route-set list --help +Usage: oci lb path-route-set list [OPTIONS] + + Lists all path route sets associated with the specified load balancer. + +Options: + --load-balancer-id TEXT The [OCID] of the load balancer associated with the + path route sets to retrieve. [required] + --from-json TEXT Provide input to this command as a JSON document from + a file. + + Options can still be provided on the command + line. If an option exists in both the JSON document + and the command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + +++++++++++++++++++++++++++++++++++++++++++++++ +$ oci lb path-route-set update --help +Usage: oci lb path-route-set update [OPTIONS] + + Overwrites an existing path route set on the specified load balancer. Use + this operation to add, delete, or alter path route rules in a path route + set. + + To add a new path route rule to a path route set, the `pathRoutes` in the + [UpdatePathRouteSetDetails] object must include both the new path route rule + to add and the existing path route rules to retain. + +Options: + --path-routes COMPLEX TYPE The set of path route rules. [required] + This + is a complex type whose value must be valid + JSON. The value can be provided as a string on + the command line or passed in as a file using + the file://path/to/file syntax. + + The + --generate-param-json-input option can be used + to generate an example of the JSON which must + be provided. We recommend storing this example + in a file, modifying it as needed and then + passing it back in via the file:// syntax. + --load-balancer-id TEXT The [OCID] of the load balancer associated + with the path route set to update. [required] + --path-route-set-name TEXT The name of the path route set to update. + Example: `path-route-set-001` [required] + --force Perform update without prompting for + confirmation. + --wait-for-state [ACCEPTED|IN_PROGRESS|FAILED|SUCCEEDED] + 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. + --max-wait-seconds INTEGER The maximum time to wait for the work request + to reach the state defined by --wait-for- + state. Defaults to 1200 seconds. + --wait-interval-seconds INTEGER + 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. + --from-json TEXT Provide input to this command as a JSON + document from a file. + + Options can still be + provided on the command line. If an option + exists in both the JSON document and the + command line then the command line specified + value will be used + -?, -h, --help Show this message and exit. + ++++++++++++++++++++++++++++++++++++++++++++++ $ oci lb policy --help Usage: oci lb policy [OPTIONS] COMMAND [ARGS]... @@ -14549,8 +15870,7 @@ Usage: oci network vnic assign-private-ip [OPTIONS] private IP must be in the same subnet as the VNIC. This command can also be used to move an existing secondary private IP to the specified VNIC. - For more information about secondary private IPs, see [Managing IP - Addresses] + For more information about secondary private IPs, see [IP Addresses] Options: --vnic-id TEXT The OCID of the VNIC to assign the private IP @@ -14661,8 +15981,7 @@ Usage: oci network vnic unassign-private-ip [OPTIONS] This operation cannot be used with primary private IPs, which are automatically unassigned, and then deleted when the VNIC is terminated. - For more information about secondary private IPs, see [Managing IP - Addresses] + For more information about secondary private IPs, see [IP Addresses] Options: --vnic-id TEXT The OCID of the VNIC to unassign the private IP from. @@ -14837,6 +16156,43 @@ Options: type is set explicitly, the bucket is put in the Archive Storage tier. The 'storageTier' property is immutable after bucket is created. + --freeform-tags COMPLEX TYPE 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"}` + This is a complex + type whose value must be valid JSON. The value + can be provided as a string on the command + line or passed in as a file using + the + file://path/to/file syntax. + + The --generate- + param-json-input option can be used to + generate an example of the JSON which must be + provided. We recommend storing this example + in + a file, modifying it as needed and then + passing it back in via the file:// syntax. + --defined-tags COMPLEX TYPE Defined tags for this resource. Each key is + predefined and scoped to a namespace. For more + information, see [Resource Tags]. Example: + `{"Operations": {"CostCenter": "42"}}` + This is + a complex type whose value must be valid JSON. + The value can be provided as a string on the + command line or passed in as a file using + the + file://path/to/file syntax. + + The --generate- + param-json-input option can be used to + generate an example of the JSON which must be + provided. We recommend storing this example + in + a file, modifying it as needed and then + passing it back in via the file:// syntax. --from-json TEXT Provide input to this command as a JSON document from a file. @@ -14934,6 +16290,13 @@ Options: buckets. [required] --limit INTEGER The maximum number of items to return. --page TEXT The page at which to start retrieving results. + --fields [tags] Bucket summary in list of buckets includes the + 'namespace', 'name', 'compartmentId', + 'createdBy', 'timeCreated', and 'etag' fields. + This parameter can also include 'tags' + (freeformTags and definedTags). The only + supported value of this parameter is 'tags' + for now. Example 'tags'. --all Fetches all pages of results. If you provide this option, then you cannot provide the --limit option. @@ -14992,6 +16355,43 @@ Options: When `ObjectReadWithoutList` is enabled on the bucket, public access is allowed for the `GetObject` and `HeadObject` operations. + --freeform-tags COMPLEX TYPE 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"}` + This is a complex + type whose value must be valid JSON. The value + can be provided as a string on the command + line or passed in as a file using + the + file://path/to/file syntax. + + The --generate- + param-json-input option can be used to + generate an example of the JSON which must be + provided. We recommend storing this example + in + a file, modifying it as needed and then + passing it back in via the file:// syntax. + --defined-tags COMPLEX TYPE Defined tags for this resource. Each key is + predefined and scoped to a namespace. For more + information, see [Resource Tags]. Example: + `{"Operations": {"CostCenter": "42"}} + This is + a complex type whose value must be valid JSON. + The value can be provided as a string on the + command line or passed in as a file using + the + file://path/to/file syntax. + + The --generate- + param-json-input option can be used to + generate an example of the JSON which must be + provided. We recommend storing this example + in + a file, modifying it as needed and then + passing it back in via the file:// syntax. --if-match TEXT The entity tag to match. For creating and committing a multipart upload to an object, this is the entity tag of the target object. @@ -15193,7 +16593,7 @@ Commands: list Lists the objects in a bucket. put Creates a new object or overwrites an... rename Rename an object from source key to target... - restore Restore an object by specifying the name... + restore Restore one or more objects specified by... restore-status Gets the restore status for an object. resume-put Resume a previous multipart put. @@ -15859,9 +17259,14 @@ Options: $ oci os object restore --help Usage: oci os object restore [OPTIONS] - Restore an object by specifying the name parameter. + Restore one or more objects specified by objectName parameter. By default + object will be restored for 24 hours.Duration can be configured using hours + parameter. Options: + --hours INTEGER The number of hours for which this object will be + restored. By default object will be restored for 24 + hours.It can be configured using hours parameter. -ns, --namespace TEXT The top-level namespace used for the request. [required] -bn, --bucket TEXT The name of the bucket. Avoid entering confidential diff --git a/tests/test_compute.py b/tests/test_compute.py index 8b97ecf8e..bc0efb465 100644 --- a/tests/test_compute.py +++ b/tests/test_compute.py @@ -4,6 +4,7 @@ import json import os import pytest +import re import time import unittest from . import command_coverage_validator @@ -468,6 +469,34 @@ def subtest_instance_console_connections(self): self.assertEquals({}, instance_console_connection_details['data']['defined-tags']) self.assertIsNotNone(parsed_result['data']['lifecycle-state']) + private_key_file = 'C:\\Users\\oci\console.ppk' + params = [ + 'compute', 'instance-console-connection', 'get-plink-connection-string', + '--instance-console-connection-id', instance_console_connection_details['data']['id'], + '--private-key-file', private_key_file + ] + + result = self.invoke(params) + + util.validate_response(result, json_response_expected=False) + + m = re.search(oci_cli.core_cli_extended.INSTANCE_CONSOLE_CONNECTION_STRING_INTERMEDIATE_HOST_REGEX, instance_console_connection_details['data']['connection-string']) + intermediate_host = m.group(0) + + connection_template = 'Start-Job {{echo N | plink -ssh -N -i "{3}" -P 443 -l {1} {2} -L 5905:{0}:5905}}; sleep 5 ; plink -L 5900:localhost:5900 localhost -P 5905 -N -i "{3}" -l {1}' + expected_plink_connection_string = connection_template.format(instance_console_connection_details['data']['instance-id'], instance_console_connection_details['data']['id'], intermediate_host, private_key_file) + assert expected_plink_connection_string == result.output.strip() + + # confirm that error from internal call to GetConsoleConnection returns service error and non-zero status code + params = [ + 'compute', 'instance-console-connection', 'get-plink-connection-string', + '--instance-console-connection-id', 'fake-instance-console-connection-id', + '--private-key-file', private_key_file + ] + + result = self.invoke(params) + util.validate_service_error(result, error_message='ServiceError') + keep_paginating = True next_page = None all_connections = [] diff --git a/tests/test_filestorage.py b/tests/test_filestorage.py new file mode 100644 index 000000000..512b93aab --- /dev/null +++ b/tests/test_filestorage.py @@ -0,0 +1,330 @@ +# coding: utf-8 +# Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + +import json +import oci +import oci_cli +import pytest +import time + +from . import util +from . import test_config_container + + +@pytest.fixture(autouse=True, scope='function') +def vcr_fixture(request): + with test_config_container.create_vcr().use_cassette('filestorage_{name}.yml'.format(name=request.function.__name__)): + yield + + +@pytest.fixture(scope='module') +def vcn_and_subnet(runner, config_file, config_profile, network_client): + with test_config_container.create_vcr().use_cassette('filestorage_vcn_and_subnet_fixture.yml'): + # create VCN + vcn_name = util.random_name('cli_db_test_vcn') + cidr_block = "10.0.0.0/16" + vcn_dns_label = util.random_name('vcn', insert_underscore=False) + + create_vcn_details = oci.core.models.CreateVcnDetails() + create_vcn_details.cidr_block = cidr_block + create_vcn_details.display_name = vcn_name + create_vcn_details.compartment_id = util.COMPARTMENT_ID + create_vcn_details.dns_label = vcn_dns_label + + result = network_client.create_vcn(create_vcn_details) + vcn_ocid = result.data.id + assert result.status == 200 + + oci.wait_until(network_client, network_client.get_vcn(vcn_ocid), 'lifecycle_state', 'AVAILABLE', max_wait_seconds=300) + + # create subnet in first AD + subnet_name = util.random_name('python_sdk_test_subnet') + cidr_block = "10.0.1.0/24" + subnet_dns_label = util.random_name('subnet', insert_underscore=False) + '1' + + create_subnet_details = oci.core.models.CreateSubnetDetails() + create_subnet_details.compartment_id = util.COMPARTMENT_ID + create_subnet_details.availability_domain = util.availability_domain() + create_subnet_details.display_name = subnet_name + create_subnet_details.vcn_id = vcn_ocid + create_subnet_details.cidr_block = cidr_block + create_subnet_details.dns_label = subnet_dns_label + + result = network_client.create_subnet(create_subnet_details) + subnet_ocid = result.data.id + assert result.status == 200 + + oci.wait_until(network_client, network_client.get_subnet(subnet_ocid), 'lifecycle_state', 'AVAILABLE', max_wait_seconds=300) + + yield vcn_ocid, subnet_ocid + + # this code does not run inside the vcr_fixture because it is outside any test function + # thus we are explicitly creating a separate cassette for it here + with test_config_container.create_vcr().use_cassette('filestorage_vcn_and_subnet_fixture_cleanup.yml'): + # Sometimes we can't delete the subnet straight after the mount target because some VNIC is still + # hanging around. If we get a conflict, try a few times before bailing out + attempts = 0 + while attempts < 5: + try: + network_client.delete_subnet(subnet_ocid) + test_config_container.do_wait( + network_client, + network_client.get_subnet(subnet_ocid), + 'lifecycle_state', + 'TERMINATED', + max_wait_seconds=600, + succeed_on_not_found=True + ) + break + except oci.exceptions.ServiceError as e: + attempts += 1 + if e.status == 409 and attempts < 5: + time.sleep(5) + else: + raise + + network_client.delete_vcn(vcn_ocid) + + +@pytest.fixture(scope='module') +def file_system(filestorage_client, runner, config_file, config_profile): + with test_config_container.create_vcr().use_cassette('filestorage_file_system_fixture.yml'): + params = [ + 'file-system', 'create', + '--compartment-id', util.COMPARTMENT_ID, + '--availability-domain', util.availability_domain() + ] + + result = invoke(runner, config_file, config_profile, params) + util.validate_response(result) + + file_system_id = json.loads(result.output)['data']['id'] + + util.wait_until(['fs', 'file-system', 'get', '--file-system-id', file_system_id], 'ACTIVE', max_wait_seconds=300) + + yield file_system_id + + with test_config_container.create_vcr().use_cassette('filestorage_file_system_fixture_cleanup.yml'): + params = [ + 'file-system', 'delete', + '--file-system-id', file_system_id, + '--force' + ] + + invoke(runner, config_file, config_profile, params) + util.wait_until(['fs', 'file-system', 'get', '--file-system-id', file_system_id], 'DELETED', max_wait_seconds=300) + + +@pytest.fixture(scope='module') +def mount_target(filestorage_client, vcn_and_subnet, runner, config_file, config_profile): + with test_config_container.create_vcr().use_cassette('filestorage_mount_target_fixture.yml'): + vcn_id = vcn_and_subnet[0] + subnet_id = vcn_and_subnet[1] + + mount_target_name = util.random_name('cli_test_mt') + + params = [ + 'mount-target', 'create', + '--availability-domain', util.availability_domain(), + '-c', util.COMPARTMENT_ID, + '--subnet-id', subnet_id + ] + + result = invoke(runner, config_file, config_profile, params) + util.validate_response(result) + + mount_target = json.loads(result.output)['data'] + mount_target_id = mount_target['id'] + + test_config_container.do_wait( + filestorage_client, + filestorage_client.get_mount_target(mount_target_id), + 'lifecycle_state', + 'ACTIVE' + ) + + # exercise CLI get mount target + params = [ + 'mount-target', 'get', + '--mount-target-id', mount_target_id + ] + + result = invoke(runner, config_file, config_profile, params) + util.validate_response(result) + + yield mount_target + + with test_config_container.create_vcr().use_cassette('filestorage_mount_target_fixture_cleanup.yml'): + params = [ + 'mount-target', 'delete', + '--mount-target-id', mount_target_id, + '--force' + ] + + result = invoke(runner, config_file, config_profile, params) + util.validate_response(result) + + util.wait_until(['fs', 'mount-target', 'get', '--mount-target-id', mount_target_id], 'DELETED', max_wait_seconds=300) + + +def test_list_file_systems(file_system, runner, config_file, config_profile): + params = [ + 'file-system', 'list', + '--compartment-id', util.COMPARTMENT_ID, + '--availability-domain', util.availability_domain() + ] + + result = invoke(runner, config_file, config_profile, params) + util.validate_response(result) + + +def test_list_and_update_mount_targets(mount_target, runner, config_file, config_profile): + params = [ + 'mount-target', 'list', + '--compartment-id', util.COMPARTMENT_ID, + '--availability-domain', util.availability_domain() + ] + + result = invoke(runner, config_file, config_profile, params) + util.validate_response(result) + + new_display_name = util.random_name('up_cli_test_mt') + params = [ + 'mount-target', 'update', + '--mount-target-id', mount_target['id'], + '--display-name', new_display_name + ] + + result = invoke(runner, config_file, config_profile, params) + util.validate_response(result) + + assert json.loads(result.output)['data']['display-name'] == new_display_name + + +def test_crud_export_set(mount_target, runner, config_file, config_profile): + params = [ + 'export-set', 'list', + '--compartment-id', util.COMPARTMENT_ID, + '--availability-domain', util.availability_domain() + ] + + result = invoke(runner, config_file, config_profile, params) + util.validate_response(result) + + found_export_set = False + export_sets = json.loads(result.output)['data'] + for es in export_sets: + if es['id'] == mount_target['export-set-id']: + found_export_set = True + break + + assert found_export_set + + updated_export_set_name = util.random_name('up_cli_test_es') + params = [ + 'export-set', 'update', + '--export-set-id', mount_target['export-set-id'], + '--display-name', updated_export_set_name + ] + + result = invoke(runner, config_file, config_profile, params) + util.validate_response(result) + + assert json.loads(result.output)['data']['display-name'] == updated_export_set_name + + params = [ + 'export-set', 'get', + '--export-set-id', mount_target['export-set-id'] + ] + + result = invoke(runner, config_file, config_profile, params) + util.validate_response(result) + + +def test_crud_export(file_system, mount_target, runner, config_file, config_profile): + params = [ + 'export', 'create', + '--export-set-id', mount_target['export-set-id'], + '--file-system-id', file_system, + '--path', '/files' + ] + + result = invoke(runner, config_file, config_profile, params) + util.validate_response(result) + + export = json.loads(result.output)['data'] + + params = [ + 'export', 'list', + '-c', util.COMPARTMENT_ID, + '--file-system-id', file_system + ] + + result = invoke(runner, config_file, config_profile, params) + util.validate_response(result) + + # there should be one export for this fs + exports = json.loads(result.output)['data'] + assert len(exports) == 1 + + util.wait_until(['fs', 'export', 'get', '--export-id', export['id']], 'ACTIVE', max_wait_seconds=300) + + params = [ + 'export', 'delete', + '--export-id', export['id'], + '--force' + ] + + result = invoke(runner, config_file, config_profile, params) + util.validate_response(result) + + +def test_crud_snapshot(file_system, runner, config_file, config_profile): + params = [ + 'snapshot', 'list', + '--file-system-id', file_system + ] + + result = invoke(runner, config_file, config_profile, params) + util.validate_response(result) + + assert len(result.output) == 0 + + params = [ + 'snapshot', 'create', + '--file-system-id', file_system, + '--name', util.random_name('cli_snapshot') + ] + + result = invoke(runner, config_file, config_profile, params) + util.validate_response(result) + + snapshot_id = json.loads(result.output)['data']['id'] + params = [ + 'snapshot', 'get', + '--snapshot-id', snapshot_id + ] + + result = invoke(runner, config_file, config_profile, params) + util.validate_response(result) + + util.wait_until(['fs', 'snapshot', 'get', '--snapshot-id', snapshot_id], 'ACTIVE', max_wait_seconds=300) + + params = [ + 'snapshot', 'delete', + '--snapshot-id', snapshot_id, + '--force' + ] + + result = invoke(runner, config_file, config_profile, params) + util.validate_response(result) + + +def invoke(runner, config_file, config_profile, params, debug=False, root_params=None, strip_progress_bar=True, strip_multipart_stderr_output=True, ** args): + root_params = root_params or [] + if debug is True: + result = runner.invoke(oci_cli.cli, root_params + ['--debug', '--config-file', config_file, '--profile', config_profile, 'fs'] + params, ** args) + else: + result = runner.invoke(oci_cli.cli, root_params + ['--config-file', config_file, '--profile', config_profile, 'fs'] + params, ** args) + + return result diff --git a/tests/test_json_skeleton_command_invocation.py b/tests/test_json_skeleton_command_invocation.py index 7f5a92342..a4c645d36 100644 --- a/tests/test_json_skeleton_command_invocation.py +++ b/tests/test_json_skeleton_command_invocation.py @@ -5,6 +5,7 @@ import os import os.path import pytest +import random import shutil from . import test_config_container from . import util @@ -142,7 +143,7 @@ def test_list_buckets_with_override(): # This test cannot be mocked because VCR doesn't play nicely with the FileReadCallbackStream implementation in the Python SDK def test_create_update_bucket_and_put_object(): base_path = os.path.join('tests', 'resources', 'json_input') - bucket_name = 'json_skeleton_bucket_{}'.format(util.random_number_string()) + bucket_name = 'json_skeleton_bucket_{}'.format(random.randint(0, 10000)) result = invoke(['os', 'bucket', 'create', '--compartment-id', util.COMPARTMENT_ID, '--namespace', util.NAMESPACE, '--name', bucket_name, '--from-json', 'file://{}'.format(os.path.join(base_path, 'bucket_create.json'))]) parsed_result = json.loads(result.output) @@ -162,7 +163,6 @@ def test_create_update_bucket_and_put_object(): '--file', os.path.join(base_path, 'bucket_create.json'), '--from-json', 'file://{}'.format(os.path.join(base_path, 'object_put.json')) ]) - print(result.output) result = invoke([ 'os', 'object', 'head', diff --git a/tests/test_object_storage.py b/tests/test_object_storage.py index d2910151c..79989264d 100644 --- a/tests/test_object_storage.py +++ b/tests/test_object_storage.py @@ -590,6 +590,22 @@ def test_list_options(runner, config_file, config_profile, object_storage_client subtest_object_list_paging(runner, config_file, config_profile) +def test_bucket_list_with_tags(runner, config_file, config_profile): + result_tags_not_requested = invoke(runner, config_file, config_profile, ['bucket', 'list', '-ns', util.NAMESPACE, '--compartment-id', util.COMPARTMENT_ID]) + parsed_data = json.loads(result_tags_not_requested.output) + + for bucket_summary in parsed_data['data']: + assert bucket_summary['defined-tags'] is None + assert bucket_summary['freeform-tags'] is None + + result_tags_requested = invoke(runner, config_file, config_profile, ['bucket', 'list', '-ns', util.NAMESPACE, '--compartment-id', util.COMPARTMENT_ID, '--fields', 'tags']) + parsed_data = json.loads(result_tags_requested.output) + + for bucket_summary in parsed_data['data']: + assert bucket_summary['defined-tags'] is not None + assert bucket_summary['freeform-tags'] is not None + + def subtest_bucket_list(runner, config_file, config_profile): """Tests all optional parameters for oci bucket list.""" result = invoke(runner, config_file, config_profile, ['bucket', 'list', '-ns', util.NAMESPACE, '--compartment-id', util.COMPARTMENT_ID, '--limit', '1']) diff --git a/tests/test_object_storage_bulk_operations.py b/tests/test_object_storage_bulk_operations.py index 0d0ea59d6..c5acb3e2b 100644 --- a/tests/test_object_storage_bulk_operations.py +++ b/tests/test_object_storage_bulk_operations.py @@ -11,7 +11,6 @@ import shutil import six import string -import time from . import util @@ -50,7 +49,7 @@ def generate_test_data(object_storage_client): # Create a test bucket create_bucket_request = oci.object_storage.models.CreateBucketDetails() - create_bucket_request.name = 'ObjectStorageBulkGetTest_{}'.format(int(time.time())) + create_bucket_request.name = 'ObjectStorageBulkGetTest_{}'.format(random.randint(0, 1000000)) create_bucket_request.compartment_id = util.COMPARTMENT_ID object_storage_client.create_bucket(util.NAMESPACE, create_bucket_request) @@ -81,12 +80,12 @@ def generate_test_data(object_storage_client): bulk_get_object_to_content[object_name] = object_content # makedirs creates all subfolders recursively - root_bulk_put_folder = 'tests/temp/bulk_put_{}'.format(int(time.time())) + root_bulk_put_folder = 'tests/temp/bulk_put_{}'.format(random.randint(0, 1000000)) bulk_put_folder_leaf = '{}/subfolder1/subfolder2/subfolder3'.format(root_bulk_put_folder) os.makedirs(bulk_put_folder_leaf) create_bucket_request = oci.object_storage.models.CreateBucketDetails() - create_bucket_request.name = 'ObjectStorageBulkPutTest_{}'.format(int(time.time())) + create_bucket_request.name = 'ObjectStorageBulkPutTest_{}'.format(random.randint(0, 1000000)) create_bucket_request.compartment_id = util.COMPARTMENT_ID object_storage_client.create_bucket(util.NAMESPACE, create_bucket_request) @@ -237,7 +236,7 @@ def test_get_no_objects(): def test_get_multipart(object_storage_client): create_bucket_request = oci.object_storage.models.CreateBucketDetails() - create_bucket_request.name = 'ObjectStorageBulkGetMultipartsTest_{}'.format(int(time.time())) + create_bucket_request.name = 'ObjectStorageBulkGetMultipartsTest_{}'.format(random.randint(0, 1000000)) create_bucket_request.compartment_id = util.COMPARTMENT_ID object_storage_client.create_bucket(util.NAMESPACE, create_bucket_request) @@ -356,7 +355,7 @@ def test_bulk_put_default_options(): # - Try to upload with multipart disabled def test_bulk_put_with_multipart_params(object_storage_client): create_bucket_request = oci.object_storage.models.CreateBucketDetails() - create_bucket_request.name = 'ObjectStorageBulkPutMultipartsTest_{}'.format(int(time.time())) + create_bucket_request.name = 'ObjectStorageBulkPutMultipartsTest_{}'.format(random.randint(0, 1000000)) create_bucket_request.compartment_id = util.COMPARTMENT_ID object_storage_client.create_bucket(util.NAMESPACE, create_bucket_request) @@ -710,7 +709,7 @@ def test_bulk_put_get_delete_with_exclusions(object_storage_client): def test_delete_when_no_objects_in_bucket(object_storage_client): create_bucket_request = oci.object_storage.models.CreateBucketDetails() - create_bucket_request.name = 'ObjectStorageBulkDelete_{}'.format(int(time.time())) + create_bucket_request.name = 'ObjectStorageBulkDelete_{}'.format(random.randint(0, 1000000)) create_bucket_request.compartment_id = util.COMPARTMENT_ID object_storage_client.create_bucket(util.NAMESPACE, create_bucket_request) @@ -740,7 +739,7 @@ def test_delete_dry_run(): def test_delete(object_storage_client): create_bucket_request = oci.object_storage.models.CreateBucketDetails() - create_bucket_request.name = 'ObjectStorageBulkDelete_{}'.format(int(time.time())) + create_bucket_request.name = 'ObjectStorageBulkDelete_{}'.format(random.randint(0, 1000000)) create_bucket_request.compartment_id = util.COMPARTMENT_ID object_storage_client.create_bucket(util.NAMESPACE, create_bucket_request) @@ -770,7 +769,7 @@ def test_delete(object_storage_client): def test_bulk_operation_table_output_query(object_storage_client): create_bucket_request = oci.object_storage.models.CreateBucketDetails() - create_bucket_request.name = 'ObjectStorageTableOutput_{}'.format(int(time.time())) + create_bucket_request.name = 'ObjectStorageTableOutput_{}'.format(random.randint(0, 1000000)) create_bucket_request.compartment_id = util.COMPARTMENT_ID object_storage_client.create_bucket(util.NAMESPACE, create_bucket_request)