import { window } from 'vscode' ; import { KubernetesObjectKinds } from '../kubernetes/kubernetesTypes' ; import { shell } from '../shell' ; import { parseJson } from '../utils/jsonUtils' ; import { FluxSource , FluxTreeResources , FluxWorkload } from './fluxTypes' ; /**
 * Special symbols used in flux output.
 */ const enum FluxOutputSymbols { ListItem = '►' , Plus = '✚' , Success = '✔' , Failure = '✗' } /**
 * Parsed flux controller.
 */ export interface FluxController { name : string ; success : boolean ; status : string ; } /**
 * Flux prerequisite.
 */ export interface FluxPrerequisite { name : string ; success : boolean ; } class FluxTools { /**
     * Transform string to an array.
     */ private splitLines ( output ) { return output . split ( '\n' ) . filter ( str => str . length ) ; } see https async check ( ) { const result = await shell . execWithOutput ( 'flux check' , { revealOutputView : false } ) ; if ( result ?. code !== 0 ) { const stderr = result ?. stderr ; if ( stderr ) { window . showErrorMessage ( String ( result ?. stderr || '' ) ) ; } return undefined ; } const prerequisites = [ ] ; const controllers = [ ] ; let stage = '' ; for ( const line of this . splitLines ( result . stderr ) ) { if ( line === '► checking prerequisites' ) { stage = 'prerequisites' ; } else if ( line === '► checking controllers' ) { stage = 'controllers' ; } else if ( line === '✔ all checks passed' ) { stage = '' ; } else { if ( stage === 'prerequisites' ) { prerequisites . push ( line ) ; } else if ( stage === 'controllers' && ! line . startsWith ( FluxOutputSymbols . ListItem ) ) { controllers . push ( line ) ; } } } const parsedPrerequises = [ ] ; for ( const prerequisite of prerequisites ) { parsedPrerequises . push ( { name : prerequisite . slice ( 1 ) . trim ( ) , success : prerequisite . startsWith ( FluxOutputSymbols . Success ) , } ) ; } const parsedControllers = [ ] ; for ( const controller of controllers ) { let [ name , status ] = controller . split ( ':' ) ; name = name . slice ( 1 ) . trim ( ) ; status = status . split ( 'deployment' ) . pop ( ) || '' ; parsedControllers . push ( { name , success : controller . startsWith ( FluxOutputSymbols . Success ) , status , } ) ; } return { prerequisites : parsedPrerequises , controllers : parsedControllers , } ; } see https async tree ( name , namespace ) { const treeShellResult = await shell . exec ( `flux tree kustomization ${ name } -n ${ namespace } -o json` ) ; if ( treeShellResult ?. code !== 0 ) { window . showErrorMessage ( `Failed to get resources created by the workload ${ name }. ERROR: ${ treeShellResult ?. stderr }` ) ; return ; } return parseJson ( treeShellResult . stdout ) ; } see https param context async install ( context ) { let contextArg = '' ; if ( context ) { contextArg = `--context=${ context }` ; } await shell . execWithOutput ( `flux install ${ contextArg }` ) ; } see https param context async uninstall ( context = '' ) { let contextArg = '' ; if ( context ) { contextArg = `--context=${ context }` ; } await shell . execWithOutput ( `flux uninstall --silent ${ contextArg }` ) ; } see https param type param name param namespace async suspend ( type , name , namespace ) { await shell . execWithOutput ( `flux suspend ${ type } ${ name } -n ${ namespace }` ) ; } see https param type param name param namespace async resume ( type , name , namespace ) { await shell . execWithOutput ( `flux resume ${ type } ${ name } -n ${ namespace }` ) ; } see https param type param name param namespace async reconcile ( type , name , namespace ) { await shell . execWithOutput ( `flux reconcile ${ type } ${ name } -n ${ namespace }` ) ; } see https async trace ( name , kind , apiVersion , namespace ) { await shell . execWithOutput ( `flux trace ${ name } --kind=${ kind } --api-version=${ apiVersion } --namespace=${ namespace }` ) ; } see https param type param name param namespace async deleteSource ( type , name , namespace ) { await shell . execWithOutput ( `flux delete ${ type } ${ name } -n ${ namespace } --silent` ) ; } see https param name param url param branch async createSourceGit ( name , url , branch , isSSH ) { const createSourceShellResult = await shell . execWithOutput ( `flux create source git ${ name } --url ${ url } --branch ${ branch } --silent` ) ; if ( ! isSSH ) { return ; } const output = createSourceShellResult . stdout || createSourceShellResult . stderr ; let deployKey ; const lines = this . splitLines ( output ) ; const deployKeyPrefix = `${ FluxOutputSymbols . Plus } deploy key:` ; for ( const line of lines ) { if ( line . startsWith ( deployKeyPrefix ) ) { deployKey = line . slice ( deployKeyPrefix . length ) . trim ( ) ; } } if ( deployKey ) { return { deployKey , } ; } } see https async createSourceGit2 ( args ) { const urlArg = ` --url "${ args . url }"` ; const branchArg = args . branch ? ` --branch "${ args . branch }"` : '' ; const tagArg = args . tag ? ` --tag "${ args . tag }"` : '' ; const semverArg = args . semver ? ` --tag-semver "${ args . semver }"` : '' ; const intervalArg = args . interval ? ` --interval "${ args . interval }"` : '' ; const timeoutArg = args . timeout ? ` --timeout "${ args . timeout }"` : '' ; const caFileArg = args . caFile ? ` --ca-file "${ args . caFile }"` : '' ; const privateKeyFileArg = args . privateKeyFile ? ` --private-key-file "${ args . privateKeyFile }"` : '' ; const usernameArg = args . username ? ` --username "${ args . username }"` : '' ; const passwordArg = args . password ? ` --password "${ args . password }"` : '' ; const secretRefArg = args . secretRef ? ` --secret-ref "${ args . secretRef }"` : '' ; const gitImplementation = args . gitImplementation ? ` --git-implementation "${ args . gitImplementation }"` : '' ; const recurseSubmodules = args . recurseSubmodules ? ' --recurse-submodules' : '' ; const sshKeyAlgorithm = args . sshKeyAlgorithm ? ` --ssh-key-algorithm "${ args . sshKeyAlgorithm }"` : '' ; const sshEcdsaCurve = args . sshEcdsaCurve ? ` --ssh-ecdsa-curve "${ args . sshEcdsaCurve }"` : '' ; const sshRsaBits = args . sshRsaBits ? ` --ssh-rsa-bits "${ args . sshRsaBits }"` : '' ; const createSourceShellResult = await shell . execWithOutput ( `flux create source git ${ args . sourceName }${ urlArg }${ branchArg }${ tagArg }${ semverArg }${ intervalArg }${ timeoutArg }${ caFileArg }${ privateKeyFileArg }${ usernameArg }${ passwordArg }${ secretRefArg }${ gitImplementation }${ recurseSubmodules }${ sshKeyAlgorithm }${ sshEcdsaCurve }${ sshRsaBits } --silent` ) ; const output = createSourceShellResult . stdout || createSourceShellResult . stderr ; let deployKey ; const lines = this . splitLines ( output ) ; const deployKeyPrefix = `${ FluxOutputSymbols . Plus } deploy key:` ; for ( const line of lines ) { if ( line . startsWith ( deployKeyPrefix ) ) { deployKey = line . slice ( deployKeyPrefix . length ) . trim ( ) ; } } if ( ! deployKey ) { return ; } return { deployKey , } ; } async createKustomization ( kustomizationName , sourceName , kustomizationPath ) { const createKustomizationShellResult = await shell . execWithOutput ( `flux create kustomization ${ kustomizationName } --source=${ KubernetesObjectKinds . GitRepository }/${ sourceName } --path="${ kustomizationPath }" --prune=true` ) ; if ( createKustomizationShellResult ?. code !== 0 ) { window . showErrorMessage ( createKustomizationShellResult . stderr ) ; return ; } } } /**
 * Helper methods for running and parsing flux commands.
 */ export const fluxTools = new FluxTools ( ) ;