/**
 * Copyright (c) 2020, 2021 Oracle and/or its affiliates.  All rights reserved.
 * This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
 */ import fs = require ( "oci-filestorage" ) ; import core = require ( "oci-core" ) ; import identity = require ( "oci-identity" ) ; import wr = require ( "oci-workrequests" ) ; import common = require ( "oci-common" ) ; var randomNumber = require ( "random-number-csprng" ) ; const provider = new common . ConfigFileAuthenticationDetailsProvider ( ) ; /**
 * This file provides an example of how to use the File Storage service in the SDK for TypeScript.
 *
 * 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. This script also makes some assumptions about
 * the resources it will create:
 *
 * <ul>
 *   <li>The VCN created by this example will have a display name of ts_sdk_fs_example_vcn</li>
 *   <li>The subnet created by this example will have a display name of: ts_sdk_fs_example_subnet</li>
 *   <li>The VCN and subnet will have a private IP CIDR block of 10.0.0.0/16</li>
 *   <li>The file system export created by this example will have a path of /files</li>
 *   <li>Resources will be created in us-phoenix-1</li>
 *   <li>Resources will be created in the first AD returned from the ListAvailabilityDomains call</li>
 * <ul>
 */ const VCN_DISPLAY_NAME = "ts_sdk_fs_example_vcn" ; const SUBNET_DISPLAY_NAME = "ts_sdk_fs_example_subnet" ; const CIDR_BLOCK = "10.0.0.0/16" ; const EXPORT_PATH = "/files" ; const RETRY_TOKEN_LENGTH = 32 ; const RETRY_TOKEN_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" . split ( "" ) ; const DELETE_SUBNET_ATTEMPTS = 5 ; param args const args = process . argv . slice ( 2 ) ; if ( args . length !== 2 ) { console . error ( "Unexpected number of arguments received. Consult the script header comments for expected arguments" ) ; process . exit ( - 1 ) ; } const compartmentId = args [ 0 ] ; const fileSystemDisplayName = args [ 1 ] ; const fsClient = new fs . FileStorageClient ( { authenticationDetailsProvider : provider } ) ; const vcnClient = new core . VirtualNetworkClient ( { authenticationDetailsProvider : provider } ) ; const identityClient = new identity . IdentityClient ( { authenticationDetailsProvider : provider } ) ; const workRequestClient = new wr . WorkRequestClient ( { authenticationDetailsProvider : provider } ) ; const filestorageWaiter = fsClient . createWaiters ( ) ; const vcnWaiter = vcnClient . createWaiters ( workRequestClient ) ; let vcn ; let subnet ; let fileSystem ; let mountTarget ; let snapshot ; let exportModel ; ( async ( ) => { try { const availabilityDomains = await getAvailabilityDomains ( identityClient , compartmentId ) ; const adToUse = availabilityDomains [ 0 ] ; vcn = await createVcn ( vcnClient , compartmentId ) ; subnet = await createSubnet ( vcnClient , compartmentId , adToUse , vcn . id ) ; console . log ( "Created VCN and subnet" ) ; fileSystem = await createFileSystem ( fsClient , compartmentId , fileSystemDisplayName , adToUse ) ; mountTarget = await createMountTarget ( fsClient , vcnClient , compartmentId , fileSystemDisplayName + "-mnt" , adToUse , subnet ) ; await getExportSet ( fsClient , mountTarget . exportSetId ! ) ; exportModel = await createExport ( fsClient , fileSystem . id , mountTarget . exportSetId ! ) ; await listExports ( fsClient , compartmentId , fileSystem , mountTarget ) ; snapshot = await createSnapshot ( fsClient , fileSystem ) ; console . log ( "Clean Up" ) ; console . log ( "==========" ) ; if ( snapshot !== undefined ) { await deleteSnapshot ( fsClient , snapshot ) ; console . log ( "Deleted snapshot" ) ; } if ( exportModel !== undefined ) { await deleteExport ( fsClient , exportModel ) ; console . log ( "Deleted export" ) ; } if ( mountTarget !== undefined ) { await deleteMountTarget ( fsClient , mountTarget ) ; console . log ( "Deleted mount target" ) ; } if ( fileSystem !== undefined ) { await deleteFileSystem ( fsClient , fileSystem ) ; console . log ( "Deleted file system" ) ; } if ( subnet !== undefined ) { await deleteSubnet ( vcnClient , subnet ) ; console . log ( "Deleted subnet" ) ; } if ( vcn !== undefined ) { await deleteVcn ( vcnClient , vcn ) ; console . log ( "Deleted VCN" ) ; } } catch ( error ) { throw " Not able to execut File Storage example. Error:" + error ; } } ) ( ) ; param identityClient param compartmentId return async function getAvailabilityDomains ( client , compartmentId ) { const request = { compartmentId : compartmentId } ; const response = await client . listAvailabilityDomains ( request ) ; return response . items ; } param vcnClient param compartmentId return async function createVcn ( client , compartmentId ) { const createVcnDetails = { cidrBlock : CIDR_BLOCK , compartmentId : compartmentId , displayName : VCN_DISPLAY_NAME } ; const request = { createVcnDetails : createVcnDetails } ; const response = await client . createVcn ( request ) ; const getVcnRequest = { vcnId : response . vcn . id } ; const getVcnResponse = await vcnWaiter . forVcn ( getVcnRequest , core . models . Vcn . LifecycleState . Available ) ; return getVcnResponse ! . vcn ; } param vcnClient param compartmentId param availabilityDomain param vcnId return async function createSubnet ( client , compartmentId , availabilityDomain , vcnId ) { const createSubnetDetails = { availabilityDomain : availabilityDomain . name , compartmentId : compartmentId , displayName : SUBNET_DISPLAY_NAME , vcnId : vcnId , cidrBlock : CIDR_BLOCK } ; const request = { createSubnetDetails : createSubnetDetails } ; const response = await client . createSubnet ( request ) ; const getSubnetRequest = { subnetId : response . subnet . id } ; const getSubnetResponse = await vcnWaiter . forSubnet ( getSubnetRequest , core . models . Subnet . LifecycleState . Available ) ; return getSubnetResponse ! . subnet ; } param fsClient param compartmentId param availabilityDomain return async function createFileSystem ( client , compartmentId , fileSystemDisplayName , adToUse ) { console . log ( "Creating file system" ) ; console . log ( "=======================================" ) ; const retryToken = await getRetryToken ( RETRY_TOKEN_LENGTH ) ; const createFileSystemDetails = { displayName : fileSystemDisplayName , compartmentId : compartmentId , availabilityDomain : adToUse . name ! } ; const request = { createFileSystemDetails : createFileSystemDetails , opcRetryToken : retryToken } ; const response = await client . createFileSystem ( request ) ; console . log ( "Created file system: " + response . fileSystem ) ; console . log ( "Waited for file system to become available" ) ; const getFsSyetemRequest = { fileSystemId : response . fileSystem . id } ; const getFileSystemResponse = await filestorageWaiter . forFileSystem ( getFsSyetemRequest , fs . models . FileSystem . LifecycleState . Active ) ; const createFileSystemRequestRetry = { createFileSystemDetails : createFileSystemDetails , opcRetryToken : retryToken } ; const createWithRetryTokenResponse = await client . createFileSystem ( createFileSystemRequestRetry ) ; console . log ( "Try and create the file system again with the same retry token: " + createWithRetryTokenResponse . fileSystem ) ; console . log ( "same resource? " + createWithRetryTokenResponse . fileSystem . id === getFileSystemResponse ! . fileSystem . id ) ; return getFileSystemResponse ! . fileSystem ; } param fsClient param vcnClient param compartmentId param displayName param availabilityDomain param subnet return async function createMountTarget ( fsClient , vcnClient , compartmentId , displayName , availabilityDomain , subnet ) { console . log ( "Creating mount target" ) ; console . log ( "=======================================" ) ; const retryToken = await getRetryToken ( RETRY_TOKEN_LENGTH ) ; const createMountTargetDetails = { availabilityDomain : availabilityDomain . name , subnetId : subnet . id , compartmentId : compartmentId , displayName : displayName } ; const createMountTargetRequest = { createMountTargetDetails : createMountTargetDetails , opcRetryToken : retryToken } ; const createMountTargetResponse = await fsClient . createMountTarget ( createMountTargetRequest ) ; console . log ( "Created mount target: " + createMountTargetResponse . mountTarget ) ; console . log ( " waiting for mount target to be active" ) ; const getMtTargetRequest = { mountTargetId : createMountTargetResponse . mountTarget . id } ; const getMountTargetResponse = await filestorageWaiter . forMountTarget ( getMtTargetRequest , fs . models . MountTarget . LifecycleState . Active ) ; const requestWithRetryToken = { createMountTargetDetails : createMountTargetDetails , opcRetryToken : retryToken } ; const createWithRetryTokenResponse = await fsClient . createMountTarget ( requestWithRetryToken ) ; console . log ( "Try and create the mount target again with the same retry token: " + createWithRetryTokenResponse . mountTarget ) ; console . log ( " Same Resource?" + createWithRetryTokenResponse . mountTarget . id === getMountTargetResponse ! . mountTarget . id ) ; const getMtTargetReq = { mountTargetId : getMountTargetResponse ! . mountTarget . id } ; const getMtTargetRes = await fsClient . getMountTarget ( getMtTargetReq ) ; const mountTargetPrivateIpId = getMtTargetRes . mountTarget . privateIpIds [ 0 ] ; const privateIpRequest = { privateIpId : mountTargetPrivateIpId } ; const getPrivateIpResponse = await vcnClient . getPrivateIp ( privateIpRequest ) ; console . log ( "Mount target private Ip:" + getPrivateIpResponse . privateIp ) ; return getMountTargetResponse ! . mountTarget ; } param exportSetId async function getExportSet ( client , exportSetId ) { console . log ( "Get export set for mount target" ) ; console . log ( "===============================" ) ; const request = { exportSetId : exportSetId } ; const response = await client . getExportSet ( request ) ; console . log ( "Export set for mount target: " + response . exportSet ) ; } param fsClient param fileSystemId param exportSetId return async function createExport ( client , fileSystemId , exportSetId ) { console . log ( "Creating export" ) ; console . log ( "=================" ) ; const retryToken = await getRetryToken ( RETRY_TOKEN_LENGTH ) ; const createDetails = { exportSetId : exportSetId , fileSystemId : fileSystemId , path : EXPORT_PATH } ; const createExportRequest = { createExportDetails : createDetails , opcRetryToken : retryToken } ; const response = await client . createExport ( createExportRequest ) ; console . log ( "Created export: " + response . export ) ; console . log ( "Waiting for export to become available" ) ; const getExportRequest = { exportId : response . export . id } ; const getExportResponse = await filestorageWaiter . forExport ( getExportRequest , fs . models . Export . LifecycleState . Active ) ; const createExportWithRetryRequest = { createExportDetails : createDetails , opcRetryToken : retryToken } ; const createExportWithRetryResponse = await client . createExport ( createExportWithRetryRequest ) ; console . log ( "Try and create the export again with the same retry token" ) ; console . log ( "same Resource? " + createExportWithRetryResponse . export . id === getExportResponse ! . export . id ) ; return getExportResponse ! . export ; } param fsClient param compartmentId param fileSystem param mountTarget async function listExports ( client , compartmentId , fileSystem , mountTarget ) { const listExportRequest = { compartmentId : compartmentId } ; console . log ( " Listing exports by compartment Id" ) ; let listExportResponse ; do { listExportResponse = await client . listExports ( listExportRequest ) ; for ( let e of listExportResponse . items ) { console . log ( "Export Set : " + e ) ; } listExportRequest . page = listExportResponse . opcNextPage ; } while ( listExportResponse . opcNextPage != null ) ; listExportRequest . page = undefined ; listExportRequest . exportSetId = mountTarget . exportSetId ; console . log ( " Listing exports by Export Set" ) ; do { listExportResponse = await client . listExports ( listExportRequest ) ; for ( let e of listExportResponse . items ) { console . log ( "Export Set : " + e ) ; } listExportRequest . page = listExportResponse . opcNextPage ; } while ( listExportResponse . opcNextPage != null ) ; listExportRequest . page = undefined ; listExportRequest . fileSystemId = fileSystem . id ; console . log ( " Listing exports by File System" ) ; do { listExportResponse = await client . listExports ( listExportRequest ) ; for ( let e of listExportResponse . items ) { console . log ( "Export Set : " + e ) ; } listExportRequest . page = listExportResponse . opcNextPage ; } while ( listExportResponse . opcNextPage != null ) ; } param fsClient param fileSystem async function createSnapshot ( client , fileSystem ) { console . log ( "Creating snapshot" ) ; console . log ( "====================" ) ; const retryToken = await getRetryToken ( RETRY_TOKEN_LENGTH ) ; const createSnapshotDetails = { name : "Example_SnapShot" , fileSystemId : fileSystem . id } ; const createSnapshotRequest = { createSnapshotDetails : createSnapshotDetails , opcRetryToken : retryToken } ; const createSnapshotResponse = await client . createSnapshot ( createSnapshotRequest ) ; console . log ( "created snapshot" + createSnapshotResponse . snapshot ) ; console . log ( "Waiting for snapshot to become available" ) ; const getSnapShotRequest = { snapshotId : createSnapshotResponse . snapshot . id } ; const getSnapShotResponse = await filestorageWaiter . forSnapshot ( getSnapShotRequest , fs . models . Snapshot . LifecycleState . Active ) ; const createSnapshotRequestWithRetry = { createSnapshotDetails : createSnapshotDetails , opcRetryToken : retryToken } ; const createSnapshotResponseRetry = await client . createSnapshot ( createSnapshotRequestWithRetry ) ; console . log ( "created snapshot" + createSnapshotResponseRetry . snapshot ) ; console . log ( " same resource? " + createSnapshotResponseRetry . snapshot . id === getSnapShotResponse ! . snapshot . id ) ; return getSnapShotResponse ! . snapshot ; } param fsClient param snapshot async function deleteSnapshot ( client , snapshot ) { const request = { snapshotId : snapshot . id } ; await client . deleteSnapshot ( request ) ; const getSnapshotRequest = { snapshotId : snapshot . id } ; await filestorageWaiter . forSnapshot ( getSnapshotRequest , fs . models . Snapshot . LifecycleState . Deleted ) ; } param fsClient param export async function deleteExport ( client , exportModel ) { const request = { exportId : exportModel . id } ; await client . deleteExport ( request ) ; const getExportRequest = { exportId : exportModel . id } ; await filestorageWaiter . forExport ( getExportRequest , fs . models . Export . LifecycleState . Deleted ) ; } param fsClient param mountTarget throws async function deleteMountTarget ( client , mountTarget ) { const request = { mountTargetId : mountTarget . id } ; await client . deleteMountTarget ( request ) ; const getMountTargetRequest = { mountTargetId : mountTarget . id } ; await filestorageWaiter . forMountTarget ( getMountTargetRequest , fs . models . MountTarget . LifecycleState . Deleted ) ; } param fsClient param fileSystem async function deleteFileSystem ( client , fileSystem ) { const request = { fileSystemId : fileSystem . id } ; await client . deleteFileSystem ( request ) ; const getFileSystemRequest = { fileSystemId : fileSystem . id } ; await filestorageWaiter . forFileSystem ( getFileSystemRequest , fs . models . FileSystem . LifecycleState . Deleted ) ; } param vcnClient param subnet async function deleteSubnet ( client , subnet ) { let numAttempts = 0 ; while ( true ) { try { const deleteSubnetRequest = { subnetId : subnet . id } ; await client . deleteSubnet ( deleteSubnetRequest ) ; break ; } catch ( e ) { numAttempts ++ ; if ( e . statusCode === 409 && numAttempts < DELETE_SUBNET_ATTEMPTS ) { await delay ( 10 ) ; } else { throw e ; } } } await delay ( 10 ) ; } param vcnClient param vcn async function deleteVcn ( client , vcn ) { const request = { vcnId : vcn . id } ; await client . deleteVcn ( request ) ; } param tokenLength return async function getRetryToken ( tokenLength ) { let c = "" ; for ( let i = 0 ; i < tokenLength ; i ++ ) { c = c + RETRY_TOKEN_CHARS [ await randomNumber ( 0 , RETRY_TOKEN_CHARS . length ) ] ; } return c ; } async function delay ( s ) { return new Promise ( resolve => setTimeout ( resolve , s * 1000 ) ) ; }