import { Argv } from 'yargs' ; import { addCeloEnvMiddleware , doCheckOrPromptIfStagingOrProduction , DynamicEnvVar , envVar , fetchEnv , getDynamicEnvVarValue , } from './env-utils' ; import { AksClusterConfig } from './k8s-cluster/aks' ; import { AwsClusterConfig } from './k8s-cluster/aws' ; import { BaseClusterConfig , BaseClusterManager , CloudProvider } from './k8s-cluster/base' ; import { GCPClusterConfig } from './k8s-cluster/gcp' ; import { getClusterManager } from './k8s-cluster/utils' ; /**
 * Env vars corresponding to each value for the AksClusterConfig for a particular context
 */ const contextAksClusterConfigDynamicEnvVars = { clusterName : DynamicEnvVar . KUBERNETES_CLUSTER_NAME , subscriptionId : DynamicEnvVar . AZURE_SUBSCRIPTION_ID , tenantId : DynamicEnvVar . AZURE_TENANT_ID , resourceGroup : DynamicEnvVar . AZURE_KUBERNETES_RESOURCE_GROUP , regionName : DynamicEnvVar . AZURE_REGION_NAME , } ; /**
 * Env vars corresponding to each value for the AwsClusterConfig for a particular context
 */ const contextAwsClusterConfigDynamicEnvVars = { clusterName : DynamicEnvVar . KUBERNETES_CLUSTER_NAME , clusterRegion : DynamicEnvVar . AWS_CLUSTER_REGION , resourceGroupTag : DynamicEnvVar . AWS_RESOURCE_GROUP_TAG , } ; /**
 * Env vars corresponding to each value for the GCPClusterConfig for a particular context
 */ const contextGCPClusterConfigDynamicEnvVars = { clusterName : DynamicEnvVar . KUBERNETES_CLUSTER_NAME , projectName : DynamicEnvVar . GCP_PROJECT_NAME , zone : DynamicEnvVar . GCP_ZONE , } ; const clusterConfigGetterByCloudProvider = { [ CloudProvider . AWS ] : getAwsClusterConfig , [ CloudProvider . AZURE ] : getAksClusterConfig , [ CloudProvider . GCP ] : getGCPClusterConfig , } ; export function getCloudProviderFromContext ( context ) { for ( const cloudProvider of Object . values ( CloudProvider ) ) { if ( context . startsWith ( cloudProvider as string ) ) { return CloudProvider [ cloudProvider as keyof typeof CloudProvider ] ; } } throw Error ( `Context ${ context } must start with one of ${ Object . values ( CloudProvider ) }` ) ; } param context return export function getAksClusterConfig ( context ) { const azureDynamicEnvVars = getContextDynamicEnvVarValues ( contextAksClusterConfigDynamicEnvVars , context ) ; const clusterConfig = { cloudProvider : CloudProvider . AZURE , ... azureDynamicEnvVars , } ; return clusterConfig ; } param context return export function getAwsClusterConfig ( context ) { const awsDynamicEnvVars = getContextDynamicEnvVarValues ( contextAwsClusterConfigDynamicEnvVars , context ) ; const clusterConfig = { cloudProvider : CloudProvider . AZURE , ... awsDynamicEnvVars , } ; return clusterConfig ; } param context return export function getGCPClusterConfig ( context ) { const gcpDynamicEnvVars = getContextDynamicEnvVarValues ( contextGCPClusterConfigDynamicEnvVars , context ) ; const clusterConfig = { cloudProvider : CloudProvider . GCP , ... gcpDynamicEnvVars , } ; return clusterConfig ; } param dynamicEnvVars param dynamicProps param defaultValues return export function getDynamicEnvVarValues < T , P extends object > ( dynamicEnvVars , dynamicProps , defaultValues ? ) { return Object . keys ( dynamicEnvVars ) . reduce ( ( values , k ) => { const key = k as keyof T ; const dynamicEnvVar = dynamicEnvVars [ key ] ; const defaultValue = defaultValues ? defaultValues [ key ] : undefined ; const value = getDynamicEnvVarValue ( dynamicEnvVar , dynamicProps , defaultValue ) ; return { ... values , [ key ] : value , } ; } , { } ) ; } param dynamicEnvVars param context param defaultValues return export function getContextDynamicEnvVarValues < T > ( dynamicEnvVars , context , defaultValues ? ) { return getDynamicEnvVarValues ( dynamicEnvVars , { context } , defaultValues ) ; } /**
 * Reads the context and switches to the appropriate Azure or AWS Cluster
 */ export async function switchToContextCluster ( celoEnv , context , checkOrPromptIfStagingOrProduction = true , skipClusterSetup = false ) { if ( ! isValidContext ( context ) ) { throw Error ( `Invalid context, must be one of ${ fetchEnv ( envVar . CONTEXTS ) }` ) ; } if ( checkOrPromptIfStagingOrProduction ) { await doCheckOrPromptIfStagingOrProduction ( ) ; } const clusterManager = getClusterManagerForContext ( celoEnv , context ) ; await clusterManager . switchToClusterContext ( skipClusterSetup , context ) ; return clusterManager ; } export function getClusterManagerForContext ( celoEnv , context ) { const cloudProvider = getCloudProviderFromContext ( context ) ; const clusterConfig = clusterConfigGetterByCloudProvider [ cloudProvider ] ( context ) ; return getClusterManager ( cloudProvider , celoEnv , clusterConfig ) ; } export function getClusterConfigForContext ( context ) { const cloudProvider = getCloudProviderFromContext ( context ) ; return clusterConfigGetterByCloudProvider [ cloudProvider ] ( context ) ; } /**
 * yargs argv type for an command that requires a context
 */ export interface ContextArgv { context : string ; } /**
 * Coerces the value of context to be all upper-case and underscore-separated
 * rather than dash-separated. If the resulting context does not match a regex
 * requiring all caps, alphanumeric, and dash-only characters
 * (must start with letter and not end with an underscore), it will throw.
 */ export function coerceContext ( rawContextStr ) { const context = rawContextStr . toUpperCase ( ) . replace ( /-/g , '_' ) ; if ( ! RegExp ( '^[A-Z][A-Z0-9_]*[A-Z0-9]$' ) . test ( context ) ) { throw Error ( `Invalid context. Raw ${ rawContextStr }, implied ${ context }` ) ; } return context ; } export function readableContext ( context ) { const readable = context . toLowerCase ( ) . replace ( /_/g , '-' ) ; if ( ! RegExp ( '^[A-Z][A-Z0-9_]*[A-Z0-9]$' ) . test ( context ) ) { throw Error ( `Invalid context. Context ${ context }, readable ${ readable }` ) ; } return readable ; } export function isValidContext ( context ) { const validContexts = fetchEnv ( envVar . CONTEXTS ) . split ( ',' ) ; const validContextsCoerced = validContexts . map ( coerceContext ) ; return validContextsCoerced . includes ( context ) ; } /**
 * Middleware for a context related command.
 * Must be one of the contexts specified in the environment
 * variable CONTEXTS.
 */ export function addOptionalContextMiddleware ( argv ) { return addCeloEnvMiddleware ( argv ) . option ( 'context' , { description : 'Context to perform the deployment in' , type : 'string' , } ) ; } export function addContextMiddleware ( argv ) { return addOptionalContextMiddleware ( argv ) . coerce ( 'context' , coerceContext ) ; }