diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 616ede45..c5a4b5ab 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -3,9 +3,17 @@ * @kcantrel # # Set the owner for all the individual samples, if the owner is known and they want to continue to maintain the sample: -/CloudFormation/deploy-fsx-ontap/ @kcantrel -/Ansible/fsx_inventory_report/ @kcantrel -/Ansible/snapmirror_report/ @kcantrel +/Infrastructure_as_Code/CloudFormation/deploy-fsx-ontap/ @kcantrel +/Infrastructure_as_Code/CloudFormation/Export-FSxN-CloudFormation/ @kcantrel +/Infrastructure_as_Code/CloudFormation/NetApp-FSxN-Custom-Resources-Samples/ @kcantrel +/Infrastructure_as_Code/Ansible/fsx_inventory_report/ @kcantrel +/Infrastructure_as_Code/Ansible/snapmirror_report/ @kcantrel +/Infrastructure_as_Code/Ansible/Volume_Management/ @kcantrel +/Infrastructure_as_Code/Terraform/Miscellaneous/ @kcantrel +/Infrastructure_as_Code/Terraform/deploy-fsx-ontap-sqlserver/ @varunrai +/Infrastructure_as_Code/Terraform/deploy-fsx-ontap-fileshare-access/ @varunrai +/Infrastructure_as_Code/Terraform/deploy-fsx-ontap/ @kcantrel +/Infrastructure_as_Code/Terraform/fsxn-replicate/ @nichollri /EKS/FSxN-as-PVC-for-EKS/ @mickeysh /EKS/Backup-EKS-Applications-with-Trident-Protect/ @kcantrel /EKS/PV-Migrate-with-Trident-Protect/ @kcantrel @@ -17,12 +25,10 @@ /Management-Utilities/fsxn-rotate-secret/ @kcantrel /Management-Utilities/warm_performance_tier/ @kcantrel /Management-Utilities/Workload-Factory-API-Samples/ @kcantrel -/Monitoring/CloudWatch-FSx/ @kcantrel -/Monitoring/LUN-monitoring/ @kcantrel -/Monitoring/auto-add-cw-alarms/ @kcantrel -/Monitoring/monitor-ontap-services/ @kcantrel -/Monitoring/ingest_nas_audit_logs_into_cloudwatch/ @kcantrel -/Terraform/deploy-fsx-ontap-sqlserver/ @varunrai -/Terraform/deploy-fsx-ontap-fileshare-access/ @varunrai -/Terraform/deploy-fsx-ontap/ @kcantrel -/Terraform/fsxn-replicate/ @nichollri +# +# All the monitoring samples have been moved to their own repo. +#/Monitoring/CloudWatch-FSx/ @kcantrel +#/Monitoring/LUN-monitoring/ @kcantrel +#/Monitoring/auto-add-cw-alarms/ @kcantrel +#/Monitoring/monitor-ontap-services/ @kcantrel +#/Monitoring/ingest_nas_audit_logs_into_cloudwatch/ @kcantrel diff --git a/Management-Utilities/Workload-Factory-API-Samples/README.md b/Management-Utilities/Workload-Factory-API-Samples/README.md index eb0e56d9..b5dda710 100644 --- a/Management-Utilities/Workload-Factory-API-Samples/README.md +++ b/Management-Utilities/Workload-Factory-API-Samples/README.md @@ -43,26 +43,40 @@ If you do create a new script, please consider contributing it back to this repo | [bluexp_organization_add](bluexp_organization_add) | This adds a new BlueXP organization (a.k.a. account). | | [bluexp_organization_delete](bluexp_organization_delete) | This deletes a BlueXP organization (a.k.a. account). | | [bluexp_organization_rename](bluexp_organization_rename) | This renames a BlueXP organization (a.k.a. account). | -| [credentials_delete](credentials_delete) | This deletes a Workload Factory credential. | +| [bluexp_organization_member_add](bluexp_organization_member_add) | This adds a member to a BlueXP organization (a.k.a. account). | +| [bluexp_organization_member_delete](bluexp_organization_member_delete) | This deletes a member from a BlueXP organization (a.k.a. account). | +| [cicd_clones_create](cicd_clones_create) | This creates a clone in the specified CI/CD project. | +| [cicd_clones_delete](cicd_clones_delete) | This deletes a clone in the specified CI/CD project. | +| [cicd_project_create](cicd_project_create) | This creates a new CI/CD project. | +| [cicd_project_delete](cicd_project_delete) | This deletes a CI/CD project. | | [credentials_create](credentials_create) | This create a Workload Factory credential. | +| [credentials_delete](credentials_delete) | This deletes a Workload Factory credential. | +| [eda_project_config_create](eda_project_config_create) | This creates a new EDA project configuration. | +| [eda_project_config_delete](eda_project_config_delete) | This deletes a EDA project configuration. | | [fsxn_credentials_set](fsxn_credentials_set) | This sets the credentials for a specified FSx for ONTAP file system. | -| [get_latency_details](get_latency_details) | Get the specific details of a latency event. | +| [get_latency_configuration](get_latency_configuration) | Get the latency configuration for the BlueXP account. | +| [get_latency_metrics](get_latency_metrics) | Get the specific details of a latency event. | | [link_associate](link_associate) | This associates a Workload Factory Link with a specified FSx for ONTAP file system. | | [link_delete](link_delete) | This deletes a Workload Factory Link. | | [link_disassociate](link_disassociate) | This disassociates a Workload Factory Link with a specified FSx for ONTAP file system. | | [link_register](link_register) | This registers a Lambda function as a Workload Factory Link. | | [list_bluexp_accts](list_bluexp_accts) | This list all the BlueXP accounts (a.k.a. organizations) that you have access to. | | [list_bluexp_connectors](list_bluexp_connectors) | This list all the BlueXP connectors that you have access to. | -| [list_bluexp_members](list_bluexp_members) | This list all members of a provided BlueXP account. | +| [list_bluexp_organization_members](list_bluexp_organization_members) | This list all members of a provided BlueXP organization. | +| [list_bluexp_roles](list_bluexp_roles) | This list all the BlueXP roles that you have access to. | | [list_bluexp_workspaces](list_bluexp_workspaces) | This list all the BlueXP workspaces that you have access to. | +| [list_cicd_clones](list_cicd_clones) | This lists all the clones that you have access to in the specified CI/CD project. | +| [list_cicd_projects](list_cicd_projects) | This lists all the CI/CD projects that you have access to. | | [list_credentials](list_credentials) | This lists all the Workload Factory credentials that you have access to. | +| [list_eda_project_config](list_eda_project_config) | This lists the EDA project configuration. | | [list_filesystems](list_filesystems) | This lists all the FSx for ONTAP file systems that you have access to in the specified AWS region. | | [list_latency_events](list_latency_events) | This lists all the latnecy events associated with the BlueXP account. | | [list_links](list_links) | This lists all the Workload Factory Links that you have access to. | | [list_snapmirrors](list_snapmirrors) | This lists all the SnapMirror relationships that are associated with the specified file system. | +| [list_snapshots](list_snapshots) | This lists all the snapshots that are associated with the specified volumes. | | [list_svms](list_svms) | This lists all the SVMs that are associated with the specified file system. | -| [list_volumes](list_volumes) | This lists all the volumes that are associated with the specified file system. | | [list_volume_cifs_shares](list_volume_cifs_shares) | This lists cifs shares associated with a volume in the specified file system. | +| [list_volumes](list_volumes) | This lists all the volumes that are associated with the specified file system. | | [show_fsxn_credentials](show_fsxn_credentials) | This shows the credentials that Workload Factory has stored for the specified FSx for ONTAP file system. | | [snapmirror_break](snapmirror_break) | This breaks the SnapMirror relationship for the specified relationship. | | [snapmirror_create](snapmirror_create) | This creates a SnapMirror relationship between the specified source volume and destination SVM. | diff --git a/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_add b/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_add index 230c6753..c5d7c3f4 100755 --- a/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_add +++ b/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_add @@ -7,12 +7,17 @@ ################################################################################ usage () { cat 1>&2 <&2 + usage +fi # # Check that the required commands are available. for cmd in jq curl; do @@ -71,7 +84,12 @@ for cmd in jq curl; do done # # Get an access token. -token=$(get_token) +if [ -z "$BEARER_TOKEN" ]; then + token=$(get_token) +else + token=$BEARER_TOKEN +fi + if [ -z "$token" ]; then echo "Failed to get a token." exit 1 @@ -79,5 +97,6 @@ fi # # Add the organization to the BlueXP workspace. echo -n "Creating organization ${ORGANIZATION_NAME}..." -run_curl "POST" "$token" "https://api.bluexp.netapp.com/tenancy/account/$ORGANIZATION_NAME" $tmpout $tmperr '{"name": "'$ORGANIZATION_NAME'", "resourceType": "organization", "type": "application/vnd.netapp.bxp.resource", "version": "1.0"}' 'application/json' +#run_curl "POST" "$token" "https://$ENDPOINT/tenancy/account/$ORGANIZATION_NAME" $tmpout $tmperr '{"name": "'$ORGANIZATION_NAME'", "resourceType": "organization", "type": "application/vnd.netapp.bxp.resource", "version": "1.0"}' 'application/json' +run_curl "POST" "$token" "https://$ENDPOINT/tenancy/account/$ORGANIZATION_NAME" $tmpout $tmperr '{"isSaasDisabled": '$GovCloud'}' 'application/json' echo "Done." diff --git a/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_delete b/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_delete index 774622ba..e0f7da32 100755 --- a/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_delete +++ b/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_delete @@ -1,18 +1,26 @@ #!/bin/bash # -# This script deletes an organization from a BlueXP account. +# This script deletes an BlueXP organization. # ################################################################################ # Display usage information then exits the script. ################################################################################ usage () { cat 1>&2 <&2 + usage +fi # # Check that the required commands are available. for cmd in jq curl; do @@ -73,12 +89,17 @@ for cmd in jq curl; do done # # Get an access token. -token=$(get_token) +if [ -z "$BEARER_TOKEN" ]; then + token=$(get_token) +else + token="$BEARER_TOKEN" +fi + if [ -z "$token" ]; then echo "Failed to get a token." exit 1 fi # echo -n "Deleting organization ${ORGANIZATION_ID}..." -run_curl "DELETE" "$token" "https://api.bluexp.netapp.com/v1/management/organizations/$ORGANIZATION_ID" $tmpout $tmperr +run_curl "DELETE" "$token" "https://$ENDPOINT/tenancy/account/$ORGANIZATION_ID" $tmpout $tmperr echo "Done." diff --git a/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_member_add b/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_member_add new file mode 100755 index 00000000..0db5924c --- /dev/null +++ b/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_member_add @@ -0,0 +1,108 @@ +#!/bin/bash +# +# This script adds a user to an BlueXP organization. +# +################################################################################ +# Display usage information then exits the script. +################################################################################ +usage () { + cat 1>&2 < + ORGANIZATION_ID= +EOF + exit 1 +} + +################################################################################ +# Main logic starts here. +################################################################################ +tmpout=$(mktemp /tmp/add_organization_to_bluexp-out.XXXXXX) +tmperr=$(mktemp /tmp/add_organization_to_bluexp-err.XXXXXX) +trap 'rm -f $tmpout $tmperr' exit +# +# Source the wf_utils file. +wf_utils=$(command -v wf_utils) +if [ -z "$wf_utils" ]; then + if [ ! -x "./wf_utils" ]; then + cat >&2 <&2 + usage +fi +# +# Check that the required commands are available. +for cmd in jq curl; do + if ! command -v $cmd &> /dev/null; then + echo "Error: The required command '$cmd' was not found. Please install it." >&2 + exit 1 + fi +done +# +# Get an access token. +if [ -z "$BEARER_TOKEN" ]; then + token=$(get_token) +else + token=$BEARER_TOKEN +fi + +if [ -z "$token" ]; then + echo "Failed to get a token." + exit 1 +fi +# +# This uses the same API that the console uses. +run_curl "POST" "$token" "https://$ENDPOINT/v1/management/organizations/$ORGANIZATION_ID/roles/$ROLE_ID/users" $tmpout $tmperr '{"type":"application/vnd.netapp.bxp.userbulk","users":[{"emailId": "'$emailAddress'"}], "version":"1.0"}' 'application/json' +echo "Done." diff --git a/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_member_delete b/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_member_delete new file mode 100755 index 00000000..ce6def1f --- /dev/null +++ b/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_member_delete @@ -0,0 +1,105 @@ +#!/bin/bash +# +# This script deletes a user from an BlueXP organization. +# +################################################################################ +# Display usage information then exits the script. +################################################################################ +usage () { + cat 1>&2 < + ORGANIZATION_ID= +EOF + exit 1 +} + +################################################################################ +# Main logic starts here. +################################################################################ +tmpout=$(mktemp /tmp/add_organization_to_bluexp-out.XXXXXX) +tmperr=$(mktemp /tmp/add_organization_to_bluexp-err.XXXXXX) +trap 'rm -f $tmpout $tmperr' exit +# +# Source the wf_utils file. +wf_utils=$(command -v wf_utils) +if [ -z "$wf_utils" ]; then + if [ ! -x "./wf_utils" ]; then + cat >&2 <&2 + usage +fi +# +# Check that the required commands are available. +for cmd in jq curl; do + if ! command -v $cmd &> /dev/null; then + echo "Error: The required command '$cmd' was not found. Please install it." >&2 + exit 1 + fi +done +# +# Get an access token. +if [ -z "$BEARER_TOKEN" ]; then + token=$(get_token) +else + token=$BEARER_TOKEN +fi + +if [ -z "$token" ]; then + echo "Failed to get a token." + exit 1 +fi +# +# This uses the same API that the console uses. +run_curl "DELETE" "$token" "https://$ENDPOINT/v1/management/organizations/$ORGANIZATION_ID/users/$USER_ID" $tmpout $tmperr +echo "Done." diff --git a/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_rename b/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_rename index 4d135c03..22653175 100755 --- a/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_rename +++ b/Management-Utilities/Workload-Factory-API-Samples/bluexp_organization_rename @@ -1,18 +1,22 @@ #!/bin/bash # -# This script renamees a BlueXP organization. +# This script renames a BlueXP organization. # ################################################################################ # Display usage information then exits the script. ################################################################################ usage () { cat 1>&2 <&2 <&2 <&2 <&2 <&2 + exit 1 +fi # # Check that the required commands are available. for cmd in jq curl; do @@ -83,12 +92,16 @@ for cmd in jq curl; do fi done -token=$(get_token) +if [ -z "$BEARER_TOKEN" ]; then + token=$(get_token) +else + token=$BEARER_TOKEN +fi if [ -z "$token" ]; then echo "Error: Failed to obtain an access token. Exiting." >&2 exit 1 fi -URL="https://api.workloads.netapp.com/accounts/${BLUEXP_ACCOUNT_ID}/builders/v1/configure" +URL="https://$ENDPOINT/accounts/${BLUEXP_ACCOUNT_ID}/builders/v1/configure" run_curl DELETE "$token" "$URL" $tmpout $tmperr echo "EDA Project filter deleted successfully." diff --git a/Management-Utilities/Workload-Factory-API-Samples/fsxn_credentials_set b/Management-Utilities/Workload-Factory-API-Samples/fsxn_credentials_set index 03a1db01..4fc61571 100755 --- a/Management-Utilities/Workload-Factory-API-Samples/fsxn_credentials_set +++ b/Management-Utilities/Workload-Factory-API-Samples/fsxn_credentials_set @@ -104,9 +104,12 @@ required_options["FILESYSTEM_ID"]='Error: The ID of the FSxN file system is requ check_required_options -if [ -n "$USER_ID" -a -n "$PASSWORD" -a -n "$SECRET_ARN" ]; then +if [ \( -n "$USER_ID" -o -n "$PASSWORD" \) -a -n "$SECRET_ARN" ]; then echo "Error: You can only provide either user_id and password OR secret_arn at the same time." >&2 usage +elif [ \( -n "$USER_ID" -o -n "$PASSWORD" \) -a \( -z "$USER_ID" -o -z "$PASSWORD" \) ]; then + echo "Error: Both user_id and password must be provided together." >&2 + usage elif [ -z "$USER_ID" -a -z "$PASSWORD" -a -z "$SECRET_ARN" ]; then echo "Error: You must provide either user_id and password OR secret_arn." >&2 usage diff --git a/Management-Utilities/Workload-Factory-API-Samples/get_latency_configuration b/Management-Utilities/Workload-Factory-API-Samples/get_latency_configuration new file mode 100755 index 00000000..5cd3b5d1 --- /dev/null +++ b/Management-Utilities/Workload-Factory-API-Samples/get_latency_configuration @@ -0,0 +1,161 @@ +#!/bin/bash +# +################################################################################ +# This script is used to get the base EDA -> Latency configuration. +# +# It is dependent on the 'wf_utils' file that is included in this repo. That +# file contains the 'get_token' function that is used to obtain a valid +# access token that is needed to run the Workload Factory APIs. The file needs +# to either be in the command search path or in the current directory. +################################################################################ + +################################################################################ +# This function just prints the usage of this script and exits the program. +################################################################################ +usage() { + cat >&2 < Latency configuration. It will not +report on the latency configuration for individual volumes. To see them use +the -j option. + +Usage: $(basename $0) -t refresh_token -a blueXP_account_ID [-j] [-n] + +Where: refresh_token - Is a refresh token used to obtain an access token needed + to run the Workload Factory APIs. You can obtain a refresh + token by going to https://services.cloud.netapp.com/refresh-token + blueXP_account_ID - is the BlueXP account ID. Run 'list_bluexp_accts' to get a + list of accounts you have access to. + -j - If specified, the output will be in JSON format instead of a table. + -n - If specified, the volume name will be included. Note, this will take extra time to run. + +Instead of passing parameters on the command line, you can set the +following environment variables: + + export REFRESH_TOKEN= + export BLUEXP_ACCOUNT_ID= +EOF + exit 1 +} + +################################################################################ +# Main logic starts here. +################################################################################ +tmpout=$(mktemp /tmp/list_volumes-out.XXXXXX) +tmpout2=$(mktemp /tmp/list_volumes-out2.XXXXXX) +tmpout3=$(mktemp /tmp/list_volumes-out3.XXXXXX) +tmperr=$(mktemp /tmp/list_volumes-err.XXXXXX) +trap 'rm -f $tmpout $tmpout2 $tmpout3 $tmperr' exit +# +# Source the wf_utils file. +wf_utils=$(command -v wf_utils) +if [ -z "$wf_utils" ]; then + if [ ! -x "./wf_utils" ]; then + cat >&2 < /dev/null; then + echo "Error: The required command '$cmd' not found. Please install it." >&2 + exit 1 + fi +done + +token=$(get_token) +if [ -z "$token" ]; then + echo "Error: Failed to obtain an access token. Exiting." >&2 + exit 1 +fi +# +# According to the documentation and some testing, this API doesn't support +# pagination, probably because it didn't used to return volume specific +# configurations. +URL="https://api.workloads.netapp.com/accounts/${BLUEXP_ACCOUNT_ID}/builders/v1/alarm/configure" +run_curl GET "$token" "$URL" $tmpout $tmperr +if [ "$JSON_OUTPUT" == true ]; then + if jq -r . $tmpout; then + : + else + cat $tmpout $tmperr + fi + exit +fi +# +# First get the default latency configuration. +jq_query='"\(.accountId),\(.createdBy),\(.status),\(.config.warning.readLatency.latencyThresholdMs),\(.config.warning.writeLatency.latencyThresholdMs),\(.config.critical.readLatency.latencyThresholdMs),\(.config.critical.writeLatency.latencyThresholdMs)"' +if jq -r "$jq_query" $tmpout > $tmpout2 2> $tmperr; then + : +else + echo "Error: Failed to parse the output from the API." >&2 + cat $tmperr >&2 + exit 1 +fi +echo "Default Latency Configuration:" +sort -f $tmpout2 | column -s, -t -R 4,5,6,7 -N "Account ID,Created By,Status,Warning Read Threshold,Warning Write Threshold,Critical Read Threshold,Critical Write Threshold" +# +# Now get the latency configuration for each volume. +jq_query='.config.filesystems | to_entries | .[] | .key + " " + (.value | to_entries | .[] | .key + " " + (.value.warning.readLatency.latencyThresholdMs | tostring) + " " + (.value.warning.writeLatency.latencyThresholdMs | tostring) + " " + (.value.critical.readLatency.latencyThresholdMs | tostring) + " " + (.value.critical.writeLatency.latencyThresholdMs | tostring) + " ")' +if jq -r "$jq_query" $tmpout > $tmpout2 2> $tmperr; then + : +else + echo "Error: Failed to parse the output from the API." >&2 + cat $tmperr >&2 + exit 1 +fi +if [ "$INCLUDE_NAMES" == false ]; then + printf "\nVolume specific Latency Configuration:\n" + sort -f $tmpout2 | column -s' ' -t -R 3,4,5,6 -N "File System ID,Volume ID,Warning Read Threshold,Warning Write Threshold,Critical Read Threshold,Critical Write Threshold" +else + # + # Get all the unique file systems: + awk '{print $1}' $tmpout2 | sort -u > $tmpout + # + # Create a lookup table of file system to volume mapping. + > $tmpout3 + for fs in $(cat $tmpout); do + list_volumes -f $fs >> $tmpout3 + done + + > $tmpout + while read fsId volId wrt wwr crt cwt; do + volumeName=$(grep $volId $tmpout3 | awk '{print $1}') + if [ -z "$volumeName" ]; then + volumeName="N/A" + fi + echo "$fsId,$volId,$volumeName,$wrt,$wwr,$crt,$cwt," >> $tmpout + done < $tmpout2 + printf "\nVolume specific Latency Configuration:\n" + sort -f $tmpout | column -s, -t -R 4,5,6,7 -N "File System ID,Volume ID,Volume Name,Warning Read Threshold,Warning Write Threshold,Critical Read Threshold,Critical Write Threshold" +fi diff --git a/Management-Utilities/Workload-Factory-API-Samples/list_bluexp_accts b/Management-Utilities/Workload-Factory-API-Samples/list_bluexp_accts index 246c3f7c..dae5d3bc 100755 --- a/Management-Utilities/Workload-Factory-API-Samples/list_bluexp_accts +++ b/Management-Utilities/Workload-Factory-API-Samples/list_bluexp_accts @@ -17,11 +17,14 @@ usage () { This script is used to list all the BlueXP accounts (a.k.a. organizations) that you have access to. -Usage is: $(basename $0) -t refresh_token +Usage is: $(basename $0) -t refresh_token [-j] [-e ENDPOINT] [-b BEARER_TOKEN] Where: refresh_token - Is a refresh token used to obtain an access token needed to run the Workload Factory APIs. You can obtain a refresh token by going to https://services.cloud.netapp.com/refresh-token + j - Output the raw JSON response from the API instead of a formatted table. + ENDPOINT - The BlueXP API endpoint to use. Default is api.bluexp.netapp.com. + BEARER_TOKEN - A valid Bearer token that can be used instead of a refresh token. Note, instead of passing parameters on the command line, you can set the following environment variables instead: @@ -52,19 +55,22 @@ fi . "$wf_utils" # # Parse the command line options. -while getopts ht: opt; do +raw=false +: "${ENDPOINT:=api.bluexp.netapp.com}" +while getopts ht:je:b: opt; do case $opt in t) REFRESH_TOKEN="$OPTARG" ;; + b) BEARER_TOKEN="$OPTARG" ;; + j) raw=true ;; + e) ENDPOINT="$OPTARG" ;; *) usage ;; esac done -# -# Declare an array of required options and the error message to display if they are not set. -declare -A required_options -required_options["REFRESH_TOKEN"]='Error: A BlueXP refresh tokon is required to run this script. It can be obtain from this web page: - https://services.cloud.netapp.com/refresh-token\n\n' -check_required_options +if [ -z "$REFRESH_TOKEN" -a -z "$BEARER_TOKEN" ]; then + echo "Error: You must provide either a refresh token or a bearer token." >&2 + usage +fi # # Check that the required commands are available. for cmd in jq curl; do @@ -74,15 +80,31 @@ for cmd in jq curl; do fi done -token=$(get_token) +if [ -z "$BEARER_TOKEN" ]; then + token=$(get_token) +else + token="$BEARER_TOKEN" +fi + if [ -z "$token" ]; then echo "Error: Failed to obtain an access token. Exiting." >&2 exit 1 fi +# +# /tenancy/account doesn't provide both the ID and UUID. +#run_curl GET "$token" https://$ENDPOINT/tenancy/account $tmpout $tmperr +run_curl GET "$token" https://$ENDPOINT/v1/management/organizations $tmpout $tmperr +if [ "$raw" = true ]; then + if jq -r . $tmpout; then + : + else + cat $tmpout $tmperr + fi + exit 0 +fi -run_curl GET "$token" https://api.bluexp.netapp.com/v1/management/organizations $tmpout $tmperr -if jq -r '.items[] | "\(.name) \(.legacyId) \(.id)"' $tmpout > $tmperr; then - cat $tmperr | column -t -N Name,ID,UUID +if jq -r '.items[] | "\(.name) \(.legacyId) \(.id) " + ((.tags[] | select (".internal:bxp:gov") | if(."internal:bxp:gov") then ."internal:bxp:gov" else empty end) | tostring) + " " + ((.tags[] | select (".internal:bxp:saas") | if(."internal:bxp:saas") then ."internal:bxp:saas" else empty end) | tostring)' $tmpout > $tmperr; then + cat $tmperr | column -t -N "Name,ID,Organization ID,GovCloud,SaaS Enabled" else echo "Error: Failed to parse the response from the API." >&2 exit 1 diff --git a/Management-Utilities/Workload-Factory-API-Samples/list_bluexp_members b/Management-Utilities/Workload-Factory-API-Samples/list_bluexp_members deleted file mode 100755 index b6970179..00000000 --- a/Management-Utilities/Workload-Factory-API-Samples/list_bluexp_members +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/bash -# -# This script is used to list all the BlueXP members that are -# associated with the BlueXP account. -# -# It is dependent on the 'wf_utils' file that is included in this repo. That -# file contains the 'get_token' function that is used to obtain a valid -# access token that is needed to run the Workload Factory APIs. The file needs -# to either be in the command search path or in the current directory. -################################################################################ - -################################################################################ -# Display usage information then exits the script. -################################################################################ -usage () { - cat >&2 < - export BLUEXP_ACCOUNT_UUID= -EOF - exit 1 -} - -tmpout=/tmp/list_bluexp_members-out.$$ -tmpout2=/tmp/list_bluexp_members-out2.$$ -tmperr=/tmp/list_bluexp_members-err.$$ -trap 'rm -f $tmpout $tmpout2 $tmperr' exit -# -# Source the wf_utils file. -wf_utils=$(command -v wf_utils) -if [ -z "$wf_utils" ]; then - if [ ! -x "./wf_utils" ]; then - cat <&2 -Error: The 'wf_utils' script was not found in the current directory or in the command search path. -It is required to run this script. You can download it from: -https://github.com/NetApp/FSx-ONTAP-samples-scripts/tree/main/Management-Utilities/Workload-Factory-API-Samples -EOF - exit 1 - else - wf_utils=./wf_utils - fi -fi -. "$wf_utils" -# -# Parse the command line options. -while getopts ht:u: opt; do - case $opt in - t) REFRESH_TOKEN="$OPTARG" ;; - u) BLUEXP_ACCOUNT_UUID="$OPTARG" ;; - *) usage ;; - esac -done -# -# Declare an array of required options and the error message to display if they are not set. -declare -A required_options -required_options["REFRESH_TOKEN"]='Error: A BlueXP refresh tokon is required to run this script. It can be obtain from this web page: - https://services.cloud.netapp.com/refresh-token\n\n' -required_options["BLUEXP_ACCOUNT_UUID"]='Error: A BlueXP account UUID is required to run this script. -You can see the list of accounts you have access to by running the "list_bluexp_accts" script -found in this GitHub repository: https://github.com/NetApp/FSx-ONTAP-samples-scripts/tree/main/Management-Utilities/Workload-Factory-API-Samples\n\n' - -check_required_options -# -# Check that the required commands are available. -for cmd in jq curl; do - if ! command -v $cmd &> /dev/null; then - echo "Error: The required command '$cmd' was not found. Please install it." >&2 - exit 1 - fi -done - -token=$(get_token) -if [ -z "$token" ]; then - echo "Error: Failed to obtain an access token. Exiting." >&2 - exit 1 -fi -filter=$(urlencode "userType ne 'agent'") -numPerPage=1000 -run_curl GET "$token" "https://api.bluexp.netapp.com/v1/management/organizations/$BLUEXP_ACCOUNT_UUID/users?limit=${numPerPage}&filter=$filter" $tmpout $tmperr "" "application/vnd.netapp.bxp.users.extended+json" -count=$(jq -r '.count' $tmpout 2> /dev/null) -if [[ "$count" == 0 ]]; then - echo "No members found for the specified BlueXP account UUID: $BLUEXP_ACCOUNT_UUID." >&2 - echo "Did you provide the UUID or the iD? This script needs the UUID." >&2 - exit 0 -fi -total=$numPerPage - -jq_query='.items[] | .name + "," + if(.userType == "user") then .userType + "," + .id else .userType + "," + .auth0Id end + "," + .email' -if jq -r "$jq_query" $tmpout > $tmpout2 2> $tmperr; then - : -else - echo "Error: Failed to parse the response from the API." >&2 - cat $tmperr >&2 - exit 1 -fi -# -# Check to see if there are more. -while [ "$total" -lt "$count" ]; do - run_curl GET "$token" "https://api.bluexp.netapp.com/v1/management/organizations/$BLUEXP_ACCOUNT_UUID/users?limit=${numPerPage}&skip=${total}&filter=$filter" $tmpout $tmperr "" "application/vnd.netapp.bxp.users.extended+json" - if jq -r "$jq_query" $tmpout >> $tmpout2 2> $tmperr; then - : - else - echo "Failed to parse the output from the API." - cat $tmperr >&2 - exit 1 - fi - let total+=numPerPage -done -sort -f $tmpout2 | column -s, -t -N Name,Type,ID,Email diff --git a/Management-Utilities/Workload-Factory-API-Samples/list_bluexp_organization_members b/Management-Utilities/Workload-Factory-API-Samples/list_bluexp_organization_members new file mode 100755 index 00000000..960f2ca6 --- /dev/null +++ b/Management-Utilities/Workload-Factory-API-Samples/list_bluexp_organization_members @@ -0,0 +1,138 @@ +#!/bin/bash +# +# This script is used to list all the members assigned to a BlueXP organization. +# +# It is dependent on the 'wf_utils' file that is included in this repo. That +# file contains the 'get_token' function that is used to obtain a valid +# access token that is needed to run the Workload Factory APIs. The file needs +# to either be in the command search path or in the current directory. +################################################################################ + +################################################################################ +# Display usage information then exits the script. +################################################################################ +usage () { + cat >&2 < + export ORGANIZATION_ID= +EOF + exit 1 +} + +tmpout=/tmp/list_bluexp_user-out.$$ +tmpout2=/tmp/list_bluexp_user-out2.$$ +tmperr=/tmp/list_bluexp_user-err.$$ +trap 'rm -f $tmpout $tmpout2 $tmperr' exit +# +# Source the wf_utils file. +wf_utils=$(command -v wf_utils) +if [ -z "$wf_utils" ]; then + if [ ! -x "./wf_utils" ]; then + cat <&2 +Error: The 'wf_utils' script was not found in the current directory or in the command search path. +It is required to run this script. You can download it from: +https://github.com/NetApp/FSx-ONTAP-samples-scripts/tree/main/Management-Utilities/Workload-Factory-API-Samples +EOF + exit 1 + else + wf_utils=./wf_utils + fi +fi +. "$wf_utils" +# +# Parse the command line options. +raw=false +: "${ENDPOINT:=api.bluexp.netapp.com}" +while getopts ht:je:b:o: opt; do + case $opt in + t) REFRESH_TOKEN="$OPTARG" ;; + o) ORGANIZATION_ID="$OPTARG" ;; + b) BEARER_TOKEN="$OPTARG" ;; + j) raw=true ;; + e) ENDPOINT="$OPTARG" ;; + *) usage ;; + esac +done +# +# Declare an array of required options and the error message to display if they are not set. +declare -A required_options +required_options["ORGANIZATION_ID"]='Error: The ID of the organization is required to run this script. +You can list a list of account by running the list_bluexp_accts script found in this repo.\n\n' + +check_required_options + +if [ -z "${REFRESH_TOKEN}" -a -z "${BEARER_TOKEN}" ]; then + echo "Error: Either a refresh token or a bearer token is required to run this script." >&2 + usage +fi +# +# Check that the required commands are available. +for cmd in jq curl; do + if ! command -v $cmd &> /dev/null; then + echo "Error: The required command '$cmd' was not found. Please install it." >&2 + exit 1 + fi +done + +if [ -z "$BEARER_TOKEN" ]; then + token=$(get_token) +else + token="$BEARER_TOKEN" +fi + +if [ -z "$token" ]; then + echo "Error: Failed to obtain an access token. Exiting." >&2 + exit 1 +fi +filter="$(urlencode userType ne \"agent\")" +numPerPage=100 +count=1 # Just give it an initial value to enter the loop +total=0 +while [ $total -lt $count ]; do + run_curl GET "$token" "https://$ENDPOINT/v1/management/organizations/$ORGANIZATION_ID/users?limit=${numPerPage}&skip=${total}&filter=$filter" $tmpout $tmperr '' 'application/vnd.netapp.bxp.users.extended+json' + count="$(jq -r '.count' $tmpout 2> /dev/null)" + if [ "$count" == 0 ]; then + echo "No members found for the specified organization: $ORGANIZATION_ID." >&2 + exit 0 + fi + let total+=numPerPage + + if [ "$raw" == true ]; then + if jq -r . $tmpout; then + : + else + cat $tmpout $tmperr + exit + fi + else + jq_query='.items[] | "\(.id),\(.name)," + if(.email != null) then .email else "N/A" end + ",\(.userType)"' + if jq -r "$jq_query" $tmpout >> $tmpout2 2> $tmperr; then + : + else + echo "Error: Failed to parse the response from the API." >&2 + cat $tmperr >&2 + exit 1 + fi + fi +done + +if [ "$raw" == true ]; then + exit 0 +fi +sort -f -t, -k 4,4r -k 2,2 $tmpout2 | column -s, -t -N "ID,Name,Email,Type" diff --git a/Management-Utilities/Workload-Factory-API-Samples/list_bluexp_roles b/Management-Utilities/Workload-Factory-API-Samples/list_bluexp_roles new file mode 100755 index 00000000..f4faf1a6 --- /dev/null +++ b/Management-Utilities/Workload-Factory-API-Samples/list_bluexp_roles @@ -0,0 +1,109 @@ +#!/bin/bash +# +# This script is used to list all the BlueXP user roles that a user has +# access to. +# +# It is dependent on the 'wf_utils' file that is included in this repo. That +# file contains the 'get_token' function that is used to obtain a valid +# access token that is needed to run the Workload Factory APIs. The file needs +# to either be in the command search path or in the current directory. +################################################################################ + +################################################################################ +# Display usage information then exits the script. +################################################################################ +usage () { + cat >&2 < +EOF + exit 1 +} + +tmpout=/tmp/list_roles-out.$$ +tmperr=/tmp/list_roles-err.$$ +trap 'rm -f $tmpout $tmperr' exit +# +# Source the wf_utils file. +wf_utils=$(command -v wf_utils) +if [ -z "$wf_utils" ]; then + if [ ! -x "./wf_utils" ]; then + cat <&2 +Error: The 'wf_utils' script was not found in the current directory or in the command search path. +It is required to run this script. You can download it from: +https://github.com/NetApp/FSx-ONTAP-samples-scripts/tree/main/Management-Utilities/Workload-Factory-API-Samples +EOF + exit 1 + else + wf_utils=./wf_utils + fi +fi +. "$wf_utils" +# +# Parse the command line options. +raw=false +: "${ENDPOINT:=api.bluexp.netapp.com}" +while getopts ht:je:b: opt; do + case $opt in + t) REFRESH_TOKEN="$OPTARG" ;; + b) BEARER_TOKEN="$OPTARG" ;; + j) raw=true ;; + e) ENDPOINT="$OPTARG" ;; + *) usage ;; + esac +done +# +# Check the required parameters. +if [ -z "$REFRESH_TOKEN" -a -z "$BEARER_TOKEN" ]; then + echo "Error: Either a BlueXP refresh token or a Bearer token is required to run this script." >&2 + usage +fi +# +# Check that the required commands are available. +for cmd in jq curl; do + if ! command -v $cmd &> /dev/null; then + echo "Error: The required command '$cmd' was not found. Please install it." >&2 + exit 1 + fi +done + +if [ -z "$BEARER_TOKEN" ]; then + token=$(get_token) +else + token="$BEARER_TOKEN" +fi + +if [ -z "$token" ]; then + echo "Error: Failed to obtain an access token. Exiting." >&2 + exit 1 +fi +filter="$(urlencode isUserRole eq \"true\" and category eq \"IAM\")" +run_curl GET "$token" "https://$ENDPOINT/v1/management/roles?filter=$filter" $tmpout $tmperr +if [ "$raw" == true ]; then + if jq -r . $tmpout; then + : + else + cat $tmpout $tmperr + fi + exit 0 +fi + +if jq -r '.items[] | "\(.id),\(.name)"' $tmpout > $tmperr; then + cat $tmperr | column -s, -t -N ID,Name +else + echo "Error: Failed to parse the response from the API." >&2 + exit 1 +fi diff --git a/Management-Utilities/Workload-Factory-API-Samples/list_cicd_clones b/Management-Utilities/Workload-Factory-API-Samples/list_cicd_clones index 0c39eaa6..845f29dd 100755 --- a/Management-Utilities/Workload-Factory-API-Samples/list_cicd_clones +++ b/Management-Utilities/Workload-Factory-API-Samples/list_cicd_clones @@ -103,7 +103,7 @@ fi if [ "$raw" = true ]; then jq_query='.' else - jq_query='.items[] | "\(.name) \(.size/1024/1024/1024) \(.daysLeft) \(.volumeUuid) \(.status)"' + jq_query='.items[] | .name + " " + if(.size) then .size/1024/1024/1024 | tostring else "N/A" end + " " + if(.daysLeft) then .daysLeft | tostring else "N/A" end + " " + .volumeUuid + " " + .status' fi URL="https://api.workloads.netapp.com/accounts/${BLUEXP_ACCOUNT_ID}/builders/v1/projects/${PROJECT_ID}/operations/clones" @@ -129,7 +129,8 @@ while [ "$nextToken" != "null" ]; do fi nextToken=$(jq -r '.nextToken' $tmpout) done -if [ "$raw" = true ]; then + +if [ "$raw" == true ]; then cat $tmpout2 else sort -f $tmpout2 | column -t -N "Name,Size (GB),Days Left,Volume UUID,Status" diff --git a/Management-Utilities/Workload-Factory-API-Samples/list_cicd_projects b/Management-Utilities/Workload-Factory-API-Samples/list_cicd_projects index 4f701379..96e0e87b 100755 --- a/Management-Utilities/Workload-Factory-API-Samples/list_cicd_projects +++ b/Management-Utilities/Workload-Factory-API-Samples/list_cicd_projects @@ -16,14 +16,17 @@ usage() { cat >&2 <&2 + exit 1 +fi # # Check that the required commands are available. for cmd in jq curl; do @@ -87,7 +96,11 @@ for cmd in jq curl; do fi done -token=$(get_token) +if [ -z "$BEARER_TOKEN" ]; then + token=$(get_token) +else + token=$BEARER_TOKEN +fi if [ -z "$token" ]; then echo "Error: Failed to obtain an access token. Exiting." >&2 exit 1 @@ -99,7 +112,7 @@ else jq_query='.items[] | "\(.projectName) \(.projectId) \(.fileSystemId) \(.volumeName) \(.volumeId) \(.numberOfClones)"' fi -URL="https://api.workloads.netapp.com/accounts/${BLUEXP_ACCOUNT_ID}/builders/v1/projects" +URL="https://$ENDPOINT/accounts/${BLUEXP_ACCOUNT_ID}/builders/v1/projects" run_curl GET "$token" "$URL" $tmpout $tmperr if jq -r "$jq_query" $tmpout > $tmpout2 2> $tmperr; then : @@ -122,7 +135,8 @@ while [ "$nextToken" != "null" ]; do fi nextToken=$(jq -r '.nextToken' $tmpout) done -if [ "$raw" = true ]; then + +if [ "$raw" == true ]; then cat $tmpout2 else sort -f $tmpout2 | column -t -N "Name,Project ID,File System,Volume Name,Volume ID,Number of Clones" diff --git a/Management-Utilities/Workload-Factory-API-Samples/list_eda_project_config b/Management-Utilities/Workload-Factory-API-Samples/list_eda_project_config index 8bdd177c..cbd48b33 100755 --- a/Management-Utilities/Workload-Factory-API-Samples/list_eda_project_config +++ b/Management-Utilities/Workload-Factory-API-Samples/list_eda_project_config @@ -16,13 +16,15 @@ usage() { cat >&2 <&2 exit 1 @@ -99,7 +111,7 @@ else jq_query='.createdBy as $cb | (.items[] | select(.target == "tag") | "\(.label) \(.key) " + $cb)' fi -URL="https://api.workloads.netapp.com/accounts/${BLUEXP_ACCOUNT_ID}/builders/v1/configure" +URL="https://$ENDPOINT/accounts/${BLUEXP_ACCOUNT_ID}/builders/v1/configure" run_curl GET "$token" "$URL" $tmpout $tmperr if jq -r "$jq_query" $tmpout > $tmpout2 2> $tmperr; then : diff --git a/Management-Utilities/Workload-Factory-API-Samples/list_latency_events b/Management-Utilities/Workload-Factory-API-Samples/list_latency_events index df463fbb..7f80e6ec 100755 --- a/Management-Utilities/Workload-Factory-API-Samples/list_latency_events +++ b/Management-Utilities/Workload-Factory-API-Samples/list_latency_events @@ -127,5 +127,10 @@ done if [ "$JSON_OUTPUT" == true ]; then cat $tmpout2 else - sort -f $tmpout2 | column -s, -t -N "Timestamnp,File System Name,Volume Name,Volume ID,Region,Alert Type,Event Type,Latency,Median Latency,IOPS,Median Over Percent" + count=$(jq -r '.count' $tmpout) + if [ "$count" == "0" ]; then + echo "No latency events were found." + exit 0 + fi + sort -f $tmpout2 | column -s, -t -N "Timestamp,File System Name,Volume Name,Volume ID,Region,Alert Type,Event Type,Latency,Median Latency,IOPS,Median Over Percent" fi diff --git a/Management-Utilities/Workload-Factory-API-Samples/wf_utils b/Management-Utilities/Workload-Factory-API-Samples/wf_utils index b477375b..01bab2b0 100755 --- a/Management-Utilities/Workload-Factory-API-Samples/wf_utils +++ b/Management-Utilities/Workload-Factory-API-Samples/wf_utils @@ -20,10 +20,18 @@ # if it is, it will just return the contents of the file. If it is older than # 24 hours, it will create a new token, output it to standard out and # store it in the file. +# +# It will store the checksum of the refresh token used to create the access +# token in a file named ".blueXP_token_checksum" in the account's home +# directory. If the checksum of the current refresh token is different than +# the one stored in the file, it will create a new token and update the +# checksum file. +# ################################################################################ get_token() { tokenFile="$HOME/.blueXP_token" + tokenCksumFile="$HOME/.blueXP_token_checksum" if [ -z "$REFRESH_TOKEN" ]; then echo "Error: The REFRESH_TOKEN environment variable has not been set." >&2 @@ -31,7 +39,7 @@ get_token() { fi # # Ensure all the required commands are available. - for cmd in curl; do + for cmd in curl cksum; do if ! command -v $cmd &> /dev/null; then echo "Error: $cmd is required but not installed." >&2 exit 1 @@ -44,6 +52,17 @@ get_token() { createToken=false if [ -r $tokenFile ]; then + cksum=$(echo -n "$REFRESH_TOKEN" | cksum | awk '{print $1}') + if [ -r $tokenCksumFile ]; then + old_cksum=$(cat $tokenCksumFile) + if [ "$cksum" != "$old_cksum" ]; then + createToken=true + echo -n "$cksum" > $tokenCksumFile + fi + else + echo "$cksum" > $tokenCksumFile + createToken=true + fi let diff="$(date +%s) - $(date -r $tokenFile +%s)" if [ $diff -gt $token_valid ]; then createToken=true