import { access , link , unlink , chmod } from 'fs' ; import { resolve , basename } from 'path' ; import { promisify } from 'util' ; import { ToolingLog } from '@kbn/dev-utils' ; import { kibanaPackageJson } from '@kbn/utils' ; import { write , copyAll , mkdirp , exec , Config , Build } from '../../../lib' ; import * as dockerTemplates from './templates' ; import { TemplateContext } from './template_context' ; import { bundleDockerFiles } from './bundle_dockerfiles' ; const accessAsync = promisify ( access ) ; const linkAsync = promisify ( link ) ; const unlinkAsync = promisify ( unlink ) ; const chmodAsync = promisify ( chmod ) ; export async function runDockerGenerator ( config , log , build , flags ) { let baseOSImage = '' ; if ( flags . ubuntu ) baseOSImage = 'ubuntu:20.04' ; if ( flags . ubi ) baseOSImage = 'docker.elastic.co/ubi8/ubi-minimal:latest' ; const ubiVersionTag = 'ubi8' ; let imageFlavor = '' ; if ( flags . ubi ) imageFlavor += `-${ ubiVersionTag }` ; if ( flags . ironbank ) imageFlavor += '-ironbank' ; if ( flags . cloud ) imageFlavor += '-cloud' ; const license = 'Elastic License' ; const imageTag = `docker.elastic.co/kibana${ flags . cloud ? '-ci' : '' }/kibana` ; const version = config . getBuildVersion ( ) ; const artifactArchitecture = flags . architecture === 'aarch64' ? 'aarch64' : 'x86_64' ; const artifactPrefix = `kibana-${ version }-linux` ; const artifactTarball = `${ artifactPrefix }-${ artifactArchitecture }.tar.gz` ; const beatsArchitecture = flags . architecture === 'aarch64' ? 'arm64' : 'x86_64' ; const metricbeatTarball = `metricbeat-${ version }-linux-${ beatsArchitecture }.tar.gz` ; const filebeatTarball = `filebeat-${ version }-linux-${ beatsArchitecture }.tar.gz` ; const artifactsDir = config . resolveFromTarget ( '.' ) ; const beatsDir = config . resolveFromRepo ( '.beats' ) ; const dockerBuildDate = flags . dockerBuildDate || new Date ( ) . toISOString ( ) ; const dockerBuildDir = config . resolveFromRepo ( 'build' , 'kibana-docker' , `default${ imageFlavor }` ) ; const imageArchitecture = flags . architecture === 'aarch64' ? '-aarch64' : '' ; const dockerTargetFilename = config . resolveFromTarget ( `kibana${ imageFlavor }-${ version }-docker-image${ imageArchitecture }.tar.gz` ) ; const dependencies = [ resolve ( artifactsDir , artifactTarball ) , ... ( flags . cloud ? [ resolve ( beatsDir , metricbeatTarball ) , resolve ( beatsDir , filebeatTarball ) ] : [ ] ) , ] ; const dockerPush = config . getDockerPush ( ) ; const dockerTagQualifier = config . getDockerTagQualfiier ( ) ; const scope = { artifactPrefix , artifactTarball , imageFlavor , version , branch : kibanaPackageJson . branch , license , artifactsDir , imageTag , dockerBuildDir , dockerTargetFilename , dockerPush , dockerTagQualifier , baseOSImage , dockerBuildDate , ubi : flags . ubi , ubuntu : flags . ubuntu , cloud : flags . cloud , metricbeatTarball , filebeatTarball , ironbank : flags . ironbank , architecture : flags . architecture , revision : config . getBuildSha ( ) , } ; type HostArchitectureToDocker = Record < string , string > ; const hostTarget = { x64 : 'x64' , arm64 : 'aarch64' , } ; const buildArchitectureSupported = hostTarget [ process . arch ] === flags . architecture ; if ( flags . architecture && ! buildArchitectureSupported ) { return ; } await mkdirp ( dockerBuildDir ) ; for ( const [ , dockerTemplate ] of Object . entries ( dockerTemplates ) ) { await write ( resolve ( dockerBuildDir , dockerTemplate . name ) , dockerTemplate . generator ( scope ) ) ; } await copyAll ( config . resolveFromRepo ( 'src/dev/build/tasks/os_packages/docker_generator/resources/base' ) , dockerBuildDir ) ; if ( flags . ironbank ) { await copyAll ( config . resolveFromRepo ( 'src/dev/build/tasks/os_packages/docker_generator/resources/ironbank' ) , dockerBuildDir ) ; } await chmodAsync ( `${ resolve ( dockerBuildDir , 'build_docker.sh' ) }` , '755' ) ; if ( flags . image ) { for ( const src of dependencies ) { const file = basename ( src ) ; const dest = resolve ( dockerBuildDir , file ) ; try { await accessAsync ( src ) ; await unlinkAsync ( dest ) ; } catch ( e ) { if ( e && e . code === 'ENOENT' && e . syscall === 'access' ) { throw new Error ( `${ src } is needed in order to build the docker image.` ) ; } } await linkAsync ( src , dest ) ; } await exec ( log , `./build_docker.sh` , [ ] , { cwd : dockerBuildDir , level : 'info' , } ) ; } if ( flags . context ) { await bundleDockerFiles ( config , log , scope ) ; } }