2021-02-26 12:46:48 +01:00
const Command = require ( "../structures/Command" )
const { CommandWords } = require ( "../constants" )
2021-02-26 14:30:24 +01:00
const { lookpath } = require ( "lookpath" )
2021-02-26 18:08:28 +01:00
const { downloadFile , logErrorToFile , success , info } = require ( "../utils" )
2021-02-26 14:30:24 +01:00
const { confirmation } = require ( "../questions" )
2021-02-26 16:09:25 +01:00
const fs = require ( "fs" )
const compose = require ( "docker-compose" )
const envFile = require ( "./makeEnv" )
2021-02-26 14:30:24 +01:00
2021-02-26 16:09:25 +01:00
const BUDIBASE _SERVICES = [ "app-service" , "worker-service" ]
const ERROR _FILE = "docker-error.log"
2021-02-26 14:30:24 +01:00
const FILE _URLS = [
"https://raw.githubusercontent.com/Budibase/budibase/master/hosting/docker-compose.yaml" ,
2021-02-26 18:09:20 +01:00
"https://raw.githubusercontent.com/Budibase/budibase/master/hosting/envoy.yaml" ,
2021-02-26 14:30:24 +01:00
]
2021-02-26 18:08:28 +01:00
async function downloadFiles ( ) {
const promises = [ ]
for ( let url of FILE _URLS ) {
const fileName = url . split ( "/" ) . slice ( - 1 ) [ 0 ]
promises . push ( downloadFile ( url , ` ./ ${ fileName } ` ) )
}
await Promise . all ( promises )
}
2021-02-26 14:30:24 +01:00
async function checkDockerConfigured ( ) {
2021-02-26 18:09:20 +01:00
const error =
"docker/docker-compose has not been installed, please follow instructions at: https://docs.budibase.com/self-hosting/hosting-methods/docker-compose#installing-docker"
2021-02-26 14:30:24 +01:00
const docker = await lookpath ( "docker" )
const compose = await lookpath ( "docker-compose" )
if ( ! docker || ! compose ) {
throw error
}
}
2021-02-24 18:32:45 +01:00
2021-02-26 16:09:25 +01:00
function checkInitComplete ( ) {
if ( ! fs . existsSync ( envFile . filePath ) ) {
throw "Please run the hosting --init command before any other hosting command."
}
}
async function handleError ( func ) {
try {
await func ( )
} catch ( err ) {
if ( err && err . err ) {
logErrorToFile ( ERROR _FILE , err . err )
}
throw ` Failed to start - logs written to file: ${ ERROR _FILE } `
}
}
2021-02-26 12:46:48 +01:00
async function init ( ) {
2021-02-26 14:30:24 +01:00
await checkDockerConfigured ( )
2021-02-26 18:09:20 +01:00
const shouldContinue = await confirmation (
"This will create multiple files in current directory, should continue?"
)
2021-02-26 14:30:24 +01:00
if ( ! shouldContinue ) {
console . log ( "Stopping." )
return
}
2021-02-26 18:08:28 +01:00
await downloadFiles ( )
2021-02-26 16:09:25 +01:00
await envFile . make ( )
2021-02-26 12:46:48 +01:00
}
async function start ( ) {
2021-02-26 16:09:25 +01:00
await checkDockerConfigured ( )
checkInitComplete ( )
2021-02-26 18:08:28 +01:00
console . log ( info ( "Starting services, this may take a moment." ) )
2021-02-26 16:09:25 +01:00
const port = envFile . get ( "MAIN_PORT" )
await handleError ( async ( ) => {
2021-02-26 18:09:20 +01:00
await compose . upAll ( { cwd : "./" , log : false } )
2021-02-26 16:09:25 +01:00
} )
2021-02-26 18:09:20 +01:00
console . log (
success (
` Services started, please go to http://localhost: ${ port } for next steps. `
)
)
2021-02-26 16:09:25 +01:00
}
async function status ( ) {
await checkDockerConfigured ( )
checkInitComplete ( )
2021-02-26 18:08:28 +01:00
console . log ( info ( "Budibase status" ) )
2021-02-26 16:09:25 +01:00
await handleError ( async ( ) => {
const response = await compose . ps ( )
console . log ( response . out )
} )
2021-02-26 12:46:48 +01:00
}
async function stop ( ) {
2021-02-26 16:09:25 +01:00
await checkDockerConfigured ( )
checkInitComplete ( )
2021-02-26 18:08:28 +01:00
console . log ( info ( "Stopping services, this may take a moment." ) )
2021-02-26 16:09:25 +01:00
await handleError ( async ( ) => {
await compose . stop ( )
} )
2021-02-26 18:08:28 +01:00
console . log ( success ( "Services have been stopped successfully." ) )
2021-02-26 12:46:48 +01:00
}
async function update ( ) {
2021-02-26 16:09:25 +01:00
await checkDockerConfigured ( )
checkInitComplete ( )
2021-02-26 18:09:20 +01:00
if (
await confirmation (
"Do you wish to update you docker-compose.yaml and envoy.yaml?"
)
) {
2021-02-26 18:08:28 +01:00
await downloadFiles ( )
}
2021-02-26 16:09:25 +01:00
await handleError ( async ( ) => {
const status = await compose . ps ( )
const parts = status . out . split ( "\n" )
const isUp = parts [ 2 ] && parts [ 2 ] . indexOf ( "Up" ) !== - 1
2021-02-26 18:08:28 +01:00
if ( isUp ) {
console . log ( info ( "Stopping services, this may take a moment." ) )
await compose . stop ( )
}
console . log ( info ( "Beginning update, this may take a few minutes." ) )
2021-02-26 18:09:20 +01:00
await compose . pullMany ( BUDIBASE _SERVICES , { log : true } )
2021-02-26 16:09:25 +01:00
if ( isUp ) {
2021-02-26 18:08:28 +01:00
console . log ( success ( "Update complete, restarting services..." ) )
2021-02-26 16:09:25 +01:00
await start ( )
}
} )
2021-02-26 12:46:48 +01:00
}
const command = new Command ( ` ${ CommandWords . HOSTING } ` )
2021-02-25 15:42:50 +01:00
. addHelp ( "Controls self hosting on the Budibase platform." )
2021-02-26 12:46:48 +01:00
. addSubOption (
"--init" ,
"Configure a self hosted platform in current directory." ,
init
)
. addSubOption (
"--start" ,
"Start the configured platform in current directory." ,
start
)
2021-02-26 16:09:25 +01:00
. addSubOption (
"--status" ,
"Check the status of currently running services." ,
status
)
2021-02-26 12:46:48 +01:00
. addSubOption (
"--stop" ,
"Stop the configured platform in the current directory." ,
stop
)
. addSubOption (
"--update" ,
"Updates the Budibase images to the latest version." ,
update
)
2021-02-25 15:42:50 +01:00
2021-02-26 12:46:48 +01:00
exports . command = command