/**
 * 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 common = require ( "oci-common" ) ; import oke = require ( "oci-containerengine" ) ; import core = require ( "oci-core" ) ; import identity = require ( "oci-identity" ) ; import wr = require ( "oci-workrequests" ) ; const provider = new common . ConfigFileAuthenticationDetailsProvider ( ) ; /**
 * This class provides an example of how to create a Container Engine node pool in the SDK for TypeScript.
 * It will create a VCN and three subnets, one Container Engine cluster and add one node pool in the cluster.
 * These will be deleted at the end. The class 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_oke_example_vcn</li>
 *   <li>The subnet created by this example will have a display name of: ts_sdk_oke_example_subnet_1</li>
 *   <li>The subnet created by this example will have a display name of: ts_sdk_oke_example_subnet_2</li>
 *   <li>The subnet created by this example will have a display name of: ts_sdk_oke_example_subnet_3</li>
 *   <li>The VCN will have a private IP CIDR block of 10.0.0.0/16</li>
 *   <li>The subnets will have private IP CIDR blocks of 10.0.0.0/24, 10.0.1.0/24 and 10.0.2.0/24</li>
 *   <li>The cluster created will have hardcoded display names of ContainerEngineExampleCluster</li>
 *   <li>The node pool created will have hardcoded display names of ContainerEngineNodePoolExample</li>
 *   <li>The first two subnets are used for creating cluster</li>
 *   <li>The third subnet is used for creating node pool</li>
 *   <li>
 *      The configuration file used by service clients will be sourced from the default
 *      location (~/.oci/config) and the DEFAULT profile will be used
 *   </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_oke_example_vcn" ; const SUBNET_DISPLAY_NAMES = [ "ts_sdk_oke_example_subnet_1" , "ts_sdk_oke_example_subnet_2" , "ts_sdk_oke_example_subnet_3" ] ; const CIDR_BLOCK = "10.0.0.0/16" ; const SUBNET_CIDR_BLOCKS = [ "10.0.0.0/24" , "10.0.1.0/24" , "10.0.2.0/24" ] ; const CLUSTER_DISPLAY_NAME = "ContanerEngineClusterExample" ; const NEW_NODE_POOL_DISPLAY_NAME = "ContainerEngineNodePoolNew" ; const NODE_POOL_DISPLAY_NAME = "ContainerEngineNodePool" ; const NODE_IMAGE_NAME = "Oracle-Linux-7.6" ; const NODE_SHAPE = "VM.Standard1.1" ; const NODE_METADATA = createNodeMetadata ( ) ; let clusterId = null ; let nodePoolId = null ; const args = process . argv . slice ( 2 ) ; console . log ( args ) ; if ( args . length !== 1 ) { console . error ( "Unexpected number of arguments received. Consult the script header comments for expected arguments" ) ; process . exit ( - 1 ) ; } const compartmentId = args [ 0 ] ; const containerEngineClient = new oke . ContainerEngineClient ( { authenticationDetailsProvider : provider } ) ; const vcnClient = new core . VirtualNetworkClient ( { authenticationDetailsProvider : provider } ) ; const identityClient = new identity . IdentityClient ( { authenticationDetailsProvider : provider } ) ; const workRequestClient = new wr . WorkRequestClient ( { authenticationDetailsProvider : provider } ) ; const VirtualNetworkWaiter = new core . VirtualNetworkWaiter ( vcnClient , workRequestClient ) ; let vcn ; let subnets = new Array < core . models . Subnet > ( ) ; let lb_subnetIds = new Array < string > ( ) ; let pool_subnetIds = new Array < string > ( ) ; let cluster ; let nodePool ; ( async ( ) => { try { const availabilityDomains = await getAvailabilityDomains ( identityClient , compartmentId ) ; const adToUse = availabilityDomains [ 0 ] ; vcn = await createVcn ( vcnClient , compartmentId ) ; console . log ( "Created VCN" ) ; for ( let i = 0 ; i < 3 ; i ++ ) { const subnet = await createSubnet ( vcnClient , compartmentId , adToUse , vcn . id , SUBNET_DISPLAY_NAMES [ i ] , SUBNET_CIDR_BLOCKS [ i ] ) ; subnets . push ( subnet ) ; if ( i < 3 ) lb_subnetIds . push ( subnet . id ) ; else pool_subnetIds . push ( subnet . id ) ; console . log ( "Created Subnet" + i ) ; } let subnetIds = new Array ( ) ; for ( let subnet of subnets ) { subnetIds . push ( subnet . id ) ; } const response = await getKubernetesVersions ( containerEngineClient ) ; const kubernetesVersion = response [ 0 ] ; console . log ( "kubernetes version: " + kubernetesVersion ) ; cluster = await createCluster ( containerEngineClient , vcn . id , [ subnetIds [ 0 ] , subnetIds [ 1 ] ] , kubernetesVersion , compartmentId ) ; console . log ( "Created cluster" ) ; const quantityPerSubnet = 1 ; let keyValue = { key : "key" , value : "value" } ; let initialNodeLabels = new Array < oke . models . KeyValue > ( ) ; initialNodeLabels . push ( keyValue ) ; const availabilityDomain = adToUse . name || "" ; nodePool = await createNodePool ( containerEngineClient , compartmentId , clusterId , NODE_POOL_DISPLAY_NAME , kubernetesVersion , NODE_IMAGE_NAME , NODE_SHAPE , NODE_METADATA , initialNodeLabels , availabilityDomain , [ subnetIds [ 2 ] ] ) ; console . log ( "Created node pool" ) ; await updateNodePool ( containerEngineClient , nodePoolId , NEW_NODE_POOL_DISPLAY_NAME ) ; console . log ( "Updated Node Pool " ) ; console . log ( "Clean up the resources" ) ; if ( nodePool !== null ) { await deleteNodePool ( containerEngineClient , nodePoolId ) ; console . log ( "Deleted node pool" ) ; } if ( cluster !== null ) { await deleteCluster ( containerEngineClient , clusterId ) ; console . log ( "Deleted Cluster" ) ; } for ( let i = 0 ; i < subnets . length ; i ++ ) { if ( subnets [ i ] !== null ) { await deleteSubnet ( vcnClient , subnets [ i ] ) ; console . log ( "Deleted subnet " + i ) ; } } if ( vcn !== null ) { await deleteVcn ( vcnClient , vcn ) ; console . log ( "Deleted VCN" ) ; } } catch ( error ) { throw "Error running Container Engine nodepool example" ; } } ) ( ) ; async function getAvailabilityDomains ( client , compartmentId ) { const request = { compartmentId : compartmentId } ; const response = await client . listAvailabilityDomains ( request ) ; return response . items ; } 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 VirtualNetworkWaiter . forVcn ( getVcnRequest , core . models . Vcn . LifecycleState . Available ) ; return getVcnResponse ! . vcn ; } async function createSubnet ( client , compartmentId , availabilityDomain , vcnId , subnetName , cidrBlock ) { const createSubnetDetails = { availabilityDomain : availabilityDomain . name , compartmentId : compartmentId , displayName : subnetName , vcnId : vcnId , cidrBlock : cidrBlock } ; const request = { createSubnetDetails : createSubnetDetails } ; const response = await client . createSubnet ( request ) ; return response . subnet ; } async function getKubernetesVersions ( client ) { const getClusterOptionRequest = { clusterOptionId : "all" } ; const response = await client . getClusterOptions ( getClusterOptionRequest ) ; return response . clusterOptions . kubernetesVersions ! ; } async function createCluster ( client , vcnId , subnetIds , kubernetesVersion , compartmentId ) { let cluster = { } ; console . log ( "Creating Cluster" ) ; console . log ( "================" ) ; const clusterCreateOptions = { serviceLbSubnetIds : subnetIds } ; const createClusterDetails = { name : CLUSTER_DISPLAY_NAME , compartmentId : compartmentId , vcnId : vcnId , kubernetesVersion : kubernetesVersion , options : clusterCreateOptions } ; const request = { createClusterDetails : createClusterDetails } ; const response = await client . createCluster ( request ) ; const workRequestId = response . opcWorkRequestId ; console . log ( "cluster work request ID is: " + workRequestId ) ; const workRequestResponse = await waitForWorkRequestFinished ( containerEngineClient , workRequestId ) ; if ( isWorkRequestInSuccessState ( workRequestResponse ) ) { clusterId = await getClusterId ( workRequestResponse ) ; console . log ( "cluster ID is: " + clusterId ) ; const request = { clusterId : clusterId } ; const response = await client . getCluster ( request ) ; cluster = response . cluster ; } return cluster ; } async function waitForWorkRequestFinished ( client , workRequestId ) { const containerEngineWaiter = new oke . ContainerEngineWaiter ( client ) ; const request = { workRequestId : workRequestId } ; const response = await containerEngineWaiter . forWorkRequest ( request ) ; return response ! ; } async function isWorkRequestInSuccessState ( workRequestResponse ) { let inSuccessState = false ; const workRequestStatus = workRequestResponse . workRequest . status ! ; if ( workRequestStatus === oke . models . WorkRequestStatus . Succeeded ) { inSuccessState = true ; } return inSuccessState ; } function getClusterId ( getWorkRequestResponse ) { let clusterId = "" ; let resources = getWorkRequestResponse . workRequest . resources ! ; for ( let resource of resources ) { if ( resource . entityType === "cluster" ) clusterId = resource . identifier ! ; break ; } return clusterId ; } async function createNodePool ( client , compartmentId , clusterId , displayName , kubernetesVersion , nodeImageName , nodeShape , nodeMetaData , initialNodeLabels , availabilityDomain , subnetIds ) { let nodePool ; const nodeConfigDetails = { size : 1 , placementConfigs : [ { availabilityDomain : availabilityDomain , subnetId : subnetIds [ 0 ] } ] } ; const createNodePoolDetails = { compartmentId : compartmentId , clusterId : clusterId , name : displayName , kubernetesVersion : kubernetesVersion , nodeImageName : nodeImageName , nodeShape : nodeShape , initialNodeLabels : initialNodeLabels , nodeConfigDetails : nodeConfigDetails } ; const createNodePoolRequest = { createNodePoolDetails : createNodePoolDetails } ; const response = await client . createNodePool ( createNodePoolRequest ) ; const workRequestId = response . opcWorkRequestId ; console . log ( "Create node pool work request ID is: " + workRequestId ) ; const workRequestResponse = await waitForWorkRequestFinished ( client , workRequestId ) ; if ( isWorkRequestInSuccessState ( workRequestResponse ) ) { nodePoolId = await getWorkRequestResourceId ( workRequestResponse , "nodepool" ) ; console . log ( "Node pool ID is: " + nodePoolId ) ; const request = { nodePoolId : nodePoolId } ; const response = await client . getNodePool ( request ) ; nodePool = response . nodePool ; } return nodePool ; } async function getWorkRequestResourceId ( workRequestResponse , entityType ) { let resourceId = null ; if ( workRequestResponse . workRequest . resources !== undefined ) { const resources = workRequestResponse . workRequest . resources ! ; for ( let resource of resources ) { if ( resource . entityType === entityType ) { resourceId = resource . identifier ; } } } return resourceId ; } async function updateNodePool ( client , nodePoolId , newNodePoolName ) { const updateNodePoolDetails = { name : newNodePoolName } ; const request = { updateNodePoolDetails : updateNodePoolDetails , nodePoolId : nodePoolId } ; const response = await client . updateNodePool ( request ) ; const workRequestId = response . opcWorkRequestId ; const workRequestResponse = await waitForWorkRequestFinished ( client , workRequestId ) ; if ( isWorkRequestInSuccessState ( workRequestResponse ) ) { const request = { nodePoolId : nodePoolId } ; const response = await client . getNodePool ( request ) ; const nodePool = response . nodePool ; console . log ( "Node pool name is changed to " + nodePool . name ) ; } } async function deleteNodePool ( client , nodePoolId ) { try { const request = { nodePoolId : nodePoolId } ; const response = await client . deleteNodePool ( request ) ; const workRequestId = response . opcWorkRequestId ; await waitForWorkRequestFinished ( client , workRequestId ) ; } catch ( exception ) { console . log ( "Caught Exception while delete node pool" ) ; } } async function deleteCluster ( client , clusterId ) { const request = { clusterId : clusterId } ; const response = await client . deleteCluster ( request ) ; const workRequestId = response . opcWorkRequestId ; const workRequestResponse = await waitForWorkRequestFinished ( client , workRequestId ) ; if ( isWorkRequestInSuccessState ( workRequestResponse ) ) { const getClusterRequest = { clusterId : clusterId } ; const response = await client . getCluster ( getClusterRequest ) ; console . log ( "Cluster lifecycle state is " + response . cluster . lifecycleState ! ) ; } } async function deleteSubnet ( client , subnet ) { const deleteSubnetRequest = { subnetId : subnet . id } ; await client . deleteSubnet ( deleteSubnetRequest ) ; } async function deleteVcn ( client , vcn ) { const request = { vcnId : vcn . id } ; await client . deleteVcn ( request ) ; } function createNodeMetadata ( ) { let result = { } ; result . key1 = "value1" ; result . key2 = "value2" ; return result ; }