/**
 * Copyright 2020 Opstrace, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ import fs from "fs" ; import yaml from "js-yaml" ; import { LatestClusterConfigFileSchema , LatestClusterConfigFileSchemaType , LatestAWSInfraConfigSchema , LatestGCPInfraConfigSchema } from "./schemas" ; import { LatestAWSInfraConfigType , LatestGCPInfraConfigType } from "@opstrace/config" ; import { log , die } from "@opstrace/utils" ; /**
 * Read user-given cluster config (UCC) document from either file or stdin.
 * Validate it, interpolate with defaults, and return it. Or error out.
 *
 * Note: "cluster config" is a legacy term, we decided to call this "Opstrace
 * instance" instead, and therefore this is more of an 'instance config'.
 */ export async function uccGetAndValidate ( clusterConfigFilePath , cloudProvider ) { let uccDoc ; if ( clusterConfigFilePath === "" ) { uccDoc = await uccFromStdin ( ) ; } else { uccDoc = uccFromFile ( clusterConfigFilePath ) ; } log . debug ( "user-given cluster config doc:\n%s" , uccDoc ) ; let ucc ; try { ucc = yaml . safeLoad ( uccDoc ) ; } catch ( err ) { die ( `could not YAML-decode cluster config: ${ err . message }` ) ; } log . debug ( "user-given cluster config parsed. JSON representation:\n%s" , JSON . stringify ( ucc , null , 2 ) ) ; try { LatestClusterConfigFileSchema . validateSync ( ucc , { strict : true } ) ; } catch ( err ) { die ( `invalid instance config document: ${ err . message }` ) ; } const uccWithDefaults = LatestClusterConfigFileSchema . validateSync ( ucc ) ; let infraConfigAWS ; let infraConfigGCP ; if ( cloudProvider === "aws" ) { if ( uccWithDefaults . aws !== undefined ) { log . debug ( "ucc.aws: %s" , JSON . stringify ( uccWithDefaults . aws , null , 2 ) ) ; } else { uccWithDefaults . aws = { } ; log . info ( "infra config: `aws` not set: populate with defaults" ) ; } try { LatestAWSInfraConfigSchema . validateSync ( uccWithDefaults . aws , { strict : true } ) ; } catch ( err ) { die ( `config error: invalid value for 'aws': ${ err . message }` ) ; } infraConfigAWS = LatestAWSInfraConfigSchema . validateSync ( uccWithDefaults . aws ) ; if ( uccWithDefaults . gcp !== undefined ) { log . info ( "Provider is AWS. `gcp` is set in config. Ignore." ) ; delete uccWithDefaults . gcp ; } } if ( cloudProvider === "gcp" ) { if ( uccWithDefaults . gcp !== undefined ) { log . debug ( "ucc.gcp: %s" , JSON . stringify ( uccWithDefaults . gcp , null , 2 ) ) ; } else { uccWithDefaults . gcp = { } ; log . info ( "infra config: `gcp` not set: populate with defaults" ) ; } try { LatestGCPInfraConfigSchema . validateSync ( uccWithDefaults . gcp , { strict : true } ) ; } catch ( err ) { die ( `cluster config error: invalid value for 'gcp': ${ err . message }` ) ; } infraConfigGCP = LatestGCPInfraConfigSchema . validateSync ( uccWithDefaults . gcp ) ; if ( uccWithDefaults . aws !== undefined ) { log . info ( "Provider is GCP. `aws` is set in config. Ignore." ) ; delete uccWithDefaults . aws ; } } delete uccWithDefaults . aws ; delete uccWithDefaults . gcp ; return [ uccWithDefaults , infraConfigAWS , infraConfigGCP ] ; } function uccFromFile ( clusterConfigFilePath ) { try { return fs . readFileSync ( clusterConfigFilePath , "utf8" ) ; } catch ( err ) { return die ( `could not read file '${ clusterConfigFilePath }': ${ err . message }` ) ; } } async function uccFromStdin ( ) { log . info ( "waiting for cluster config on stdin ..." ) ; return await readTextFromStdinUntilEOF ( ) ; } async function readTextFromStdinUntilEOF ( ) { const chunks = [ ] ; for await ( const chunk of process . stdin ) chunks . push ( chunk ) ; return Buffer . concat ( chunks ) . toString ( "utf8" ) ; }