Source: server/docker.js

const { exec } = require('child_process')
const fs = require('fs')
const { nanoid } = require('nanoid')

const { logInfo, logError } = require('../log')

/**
  * @class
*/
class DockerService {

  static createDockerNetworkForContainerManagerServer(platformConfig) {
    logInfo({ message: '[DockerService] Creating docker network for comunication between containers' })
    exec(`sudo docker network create ${platformConfig.ciDockerNetworkName}`)
  }

  static stopContainer(deploymentRequest) {
    const name = deploymentRequest.image.replaceAll('/', '_')
    logInfo({ message: `Running docker stop for image with the name of ${name}` })
    return `sudo docker stop ${name} ||`
  }

  static startContainer(platformConfig, { image, containerPort, hostPort, registry, env }) {
    const name = image.replaceAll('/', '_')
    const imageUrl = !!registry ? `${registry}/${image}` : image
    const envsAsString = Object.entries(env || {}).reduce((envs, [name, value]) => `${envs} --env ${name}=${value}`, '')
    logInfo({ message: `Running docker start for image with the name of ${name} with port mapping ${hostPort}:${containerPort} and source ${imageUrl}` })
    return `sudo docker run -d -p ${hostPort}:${containerPort} --name=${name} --network=${platformConfig.ciDockerNetworkName} --network-alias=${name} --rm ${envsAsString} ${imageUrl}`
  }

  static resolveCredentials({ registry, username, authentication }) {
    const shouldAuthenticate = username || authentication

    if (!shouldAuthenticate) {
      logInfo({ message: 'No docker credentials provided, assuming image is publicly hosted' })
      return ''
    }

    logInfo({ message: `Resolving docker credentials for ${registry}` })
    return `sudo docker login ${registry} -u ${username} -p ${authentication}`
  }

  static deploy(platformConfig, deploymentRequest) {
    return new Promise(resolve => {
      logInfo({ message: 'Starting docker deployment sequence' })

      const dockerCommandScript = `'#!/bin/bash'
${DockerService.stopContainer(deploymentRequest)}
${DockerService.resolveCredentials(deploymentRequest)}
${DockerService.startContainer(platformConfig, deploymentRequest)}`

      const deploymentId = nanoid()

      const FilePaths = {
        DeploymentScript: `${__dirname}/${deploymentId}.sh`
      }

      fs.writeFileSync(FilePaths.DeploymentScript, dockerCommandScript)
      const command = exec(`bash ${FilePaths.DeploymentScript}`)

      command.stdout.on('data', data => {
        logInfo({ message: `[DockerService]: ${data}` })
      })

      command.stderr.on('data', (data) => {
        logError({ message: `[DockerService]: ${data}` })
      })

      command.on('close', code => {
        logInfo({ message: `[DockerService] command exited with code ${code}` })
        fs.unlinkSync(FilePaths.DeploymentScript)
        resolve()
      })
    })

  }

}

module.exports = {
  DockerService
}