project/Jvm.scala (92 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * license agreements; and to You under the Apache License, version 2.0: * * https://www.apache.org/licenses/LICENSE-2.0 * * This file is part of the Apache Pekko project, which was derived from Akka. */ /* * Copyright (C) 2009-2022 Lightbend Inc. <https://www.lightbend.com> */ import java.io.File import java.lang.{ ProcessBuilder => JProcessBuilder } import sbt._ import scala.sys.process.Process object Jvm { def startJvm( javaBin: File, jvmOptions: Seq[String], runOptions: Seq[String], logger: Logger, connectInput: Boolean) = { forkJava(javaBin, jvmOptions ++ runOptions, logger, connectInput) } def forkJava(javaBin: File, options: Seq[String], logger: Logger, connectInput: Boolean) = { val java = javaBin.toString val command = (java :: options.toList).toArray val builder = new JProcessBuilder(command: _*) Process(builder).run(logger, connectInput) } /** * check if the current operating system is some OS */ def isOS(os: String) = try { System.getProperty("os.name").toUpperCase.startsWith(os.toUpperCase) } catch { case _: Throwable => false } /** * convert to proper path for the operating system */ def osPath(path: String) = if (isOS("WINDOWS")) Process(Seq("cygpath", path)).lineStream.mkString else path def getPodName(hostAndUser: String, sbtLogger: Logger): String = { val command: Array[String] = Array("kubectl", "get", "pods", "-l", s"host=$hostAndUser", "--no-headers", "-o", "name") val builder = new JProcessBuilder(command: _*) sbtLogger.debug("Jvm.getPodName about to run " + command.mkString(" ")) val podName = Process(builder).!! sbtLogger.debug("Jvm.getPodName podName is " + podName) podName.stripPrefix("pod/").stripSuffix("\n") } def syncJar(jarName: String, hostAndUser: String, remoteDir: String, sbtLogger: Logger): Process = { val podName = getPodName(hostAndUser, sbtLogger) val command: Array[String] = Array("kubectl", "exec", podName, "--", "/bin/bash", "-c", s"rm -rf $remoteDir && mkdir -p $remoteDir") val builder = new JProcessBuilder(command: _*) sbtLogger.debug("Jvm.syncJar about to run " + command.mkString(" ")) val process = Process(builder).run(sbtLogger, false) if (process.exitValue() == 0) { val command: Array[String] = Array("kubectl", "cp", osPath(jarName), podName + ":" + remoteDir + "/") val builder = new JProcessBuilder(command: _*) sbtLogger.debug("Jvm.syncJar about to run " + command.mkString(" ")) Process(builder).run(sbtLogger, false) } else { process } } def forkRemoteJava( java: String, jvmOptions: Seq[String], appOptions: Seq[String], jarName: String, hostAndUser: String, remoteDir: String, logger: Logger, connectInput: Boolean, sbtLogger: Logger): Process = { val podName = getPodName(hostAndUser, sbtLogger) sbtLogger.debug("About to use java " + java) val shortJarName = new File(jarName).getName val javaCommand = List(List(java), jvmOptions, List("-cp", shortJarName), appOptions).flatten val command = Array( "kubectl", "exec", podName, "--", "/bin/bash", "-c", ("cd " :: (remoteDir :: (" ; " :: javaCommand))).mkString(" ")) sbtLogger.debug("Jvm.forkRemoteJava about to run " + command.mkString(" ")) val builder = new JProcessBuilder(command: _*) Process(builder).run(logger, connectInput) } } class JvmBasicLogger(name: String) extends BasicLogger { def jvm(message: String) = "[%s] %s".format(name, message) def log(level: Level.Value, message: => String) = System.out.synchronized { System.out.println(jvm(message)) } def trace(t: => Throwable) = System.out.synchronized { val traceLevel = getTrace if (traceLevel >= 0) System.out.print(StackTrace.trimmed(t, traceLevel)) } def success(message: => String) = log(Level.Info, message) def control(event: ControlEvent.Value, message: => String) = log(Level.Info, message) def logAll(events: Seq[LogEvent]) = System.out.synchronized { events.foreach(log) } } final class JvmLogger(name: String) extends JvmBasicLogger(name)