diff --git a/garden-service/src/plugins/go-container/go-container.ts b/garden-service/src/plugins/go-container/go-container.ts index 9a75d1fcc6..a0cb8184f8 100644 --- a/garden-service/src/plugins/go-container/go-container.ts +++ b/garden-service/src/plugins/go-container/go-container.ts @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -// import { omit, get } from "lodash" +import { omit } from "lodash" import { copy, pathExists, readFile, writeFile, ensureDir } from "fs-extra" import { createGardenPlugin } from "../../types/plugin/plugin" import { @@ -17,7 +17,7 @@ import { ContainerTaskSpec, ContainerBuildSpec, } from "../container/config" -import { joiArray, joiProviderName, joi } from "../../config/common" +import { joiProviderName, joi } from "../../config/common" import { Module } from "../../types/module" import { resolve } from "path" // import { RuntimeError, ConfigurationError } from "../../exceptions" @@ -32,6 +32,9 @@ import { ModuleConfig, baseBuildSpecSchema } from "../../config/module" import { ConfigureModuleParams } from "../../types/plugin/module/configure" import { GetBuildStatusParams } from "../../types/plugin/module/getBuildStatus" import { BuildModuleParams } from "../../types/plugin/module/build" +import { HotReloadServiceParams } from "../../types/plugin/service/hotReloadService" +import { LogEntry } from "../../logger/log-entry" +import execa = require("execa") // import { binary } from "@hapi/joi" const defaultDockerfileName = "go-container.Dockerfile" @@ -40,9 +43,8 @@ const defaultDockerfilePath = resolve(STATIC_DIR, "go-container", defaultDockerf interface GoContainerBuildSpec extends ContainerBuildSpec { debug: boolean compress: boolean | number - run: string - buildFlags: string - //other fields here + // run: string + // buildFlags: string } export interface GoContainerModuleSpec extends ContainerModuleSpec { @@ -65,22 +67,27 @@ const goKeys = { By default, Garden passes the '-w' flag to the linker to omit this information and make the resulting binaries smaller. If you do want this information, set this option to \`true\`. `) + // .example(true).default(false), .example("false"), // compress: joi.alternatives().try( // joi.boolean(), - // joi.number(), + // joi.number().integer().min(1).max(9), // ).description(dedent` - // "By default, Garden will compress the resulting Go binary with UPX \(upx.github.io\). + // By default, Garden will compress the resulting Go binary with UPX \(upx.github.io\). // This can be disabled with \`false\`, or adjusted with // an integer in the 1–9 range, where 1 is fastest and 9 is smaller. // For this functionality to work with macOS, UPX needs // to first be installed with Homebrew using \`brew install upx\`. // `) - // .example("1"), - buildFlags: joi.string() - .description("Use this to pass custom build flags to the Go compiler."), - // run: joiArray(joi.string()) - // .description("Use this to add arbitrary an arbitrary RUN command to the default Dockerfile."), + // .example(1).default(1), + // buildFlags: joi.string() + // buildFlags: joi.array().items(joi.string()) + // .description("Use this to pass custom build flags to the Go compiler."), + // run: joi.array().items(joi.string()) + // run: joi.string() + // .description("Use this to add arbitrary an arbitrary RUN command to the default Dockerfile."), + // .default([" "]), //.example([["apk", "add", "curl"]]), + } const goContainerModuleSpecSchema = containerModuleSpecSchema.keys({ @@ -96,6 +103,7 @@ export const gardenPlugin = createGardenPlugin({ dependencies: ["container"], // TODO + // ALSO REFERENCE DOCS createModuleTypes: [{ name: "go-container", base: "container", @@ -105,7 +113,7 @@ export const gardenPlugin = createGardenPlugin({ Rather than build the JAR inside the container (or in a multi-stage build) this plugin runs \`mvn package\` ahead of building the container, which tends to be much more performant, especially when building locally - with a warm artifact cache. + with a warm artifact cache.i A default Dockerfile is also provided for convenience, but you may override it by including one in the module directory. @@ -118,6 +126,7 @@ export const gardenPlugin = createGardenPlugin({ configure: configureGoContainerModule, getBuildStatus, build, + hotReloadService, }, }], }) @@ -126,9 +135,28 @@ export async function configureGoContainerModule(params: ConfigureModuleParamsomit(moduleConfig.spec, Object.keys(goKeys)) + + containerConfig.spec.hotReload = containerConfig.spec.hotReload || { + sync: [{ source: "bin", target: "/app" }], + // sync: [{ source: "bin/binary", target: "/app/binary" }], + } + + for (const service of containerConfig.spec.services) { + // service.hotReloadCommand = service.hotReloadCommand || ["ls", "/"] + service.hotReloadCommand = service.hotReloadCommand || ["/bin/sh", "/app/myscript.sh"] + } const configured = await base!({ ...params, moduleConfig: containerConfig }) + // if vlue="" valiue=default + // if (!moduleConfig.spec.build.run) { + // moduleConfig.spec.build.run = "" + // } + // containerConfig.spec.buildArgs = { + // EXTRA_RUN: moduleConfig.spec.build.run, //.join(" "), + // } + return { moduleConfig: { ...configured.moduleConfig, @@ -143,24 +171,34 @@ export async function configureGoContainerModule(params: ConfigureModuleParams) { + const { base, module, log } = params + await buildBinary(module, log, true) + console.log("I'm in the hotReloadService function.") + return base!(params) +} + +async function build(params: BuildModuleParams) { + const { base, module, log } = params + await buildBinary(module, log, false) + return base!(params) +} + async function getBuildStatus(params: GetBuildStatusParams) { // const { base, module, log } = params const { base } = params - - // await prepareBuild(module, log) - return base!(params) } -async function build(params: BuildModuleParams) { - const { base, module, log } = params +async function buildBinary(module: GoContainerModule, log: LogEntry, hotReload: boolean) { +// GoContainerModule // let { debug, compress, buildFlags, run } = module.spec let { debug } = module.spec.build - log.setState(`Starting Go build process...`) + const status = log.info(`Starting Go build process...`) // Check if any imports have changed - console.log(`Checking for new dependencies...`) + status.setState(`Checking for new dependencies...`) let tidy try { tidy = await go.exec({ @@ -170,11 +208,13 @@ async function build(params: BuildModuleParams) { }) } catch (err) { console.log(err.stderr) + status.setState(err.stderr) } +console.log(tidy.stdout) // If they did, update the vendor directory - console.log(`Downloading new dependencies...`) - if (tidy.stdout != "") { + if (tidy.stdout) { + status.setState(`Downloading new dependencies...`) await go.exec({ args: ["mod", "vendor"], cwd: module.path, @@ -182,11 +222,7 @@ async function build(params: BuildModuleParams) { }) } - try { await ensureDir(resolve(module.path, "bin")) - } catch (err) { - console.error(err) - } let buildArgs = [ "build", @@ -205,22 +241,27 @@ async function build(params: BuildModuleParams) { buildArgs = buildArgs.concat(debugArgs) } - console.log(`Building...`) + status.setState(`Building Go binary...`) + let goOutput: any = "default go" try { - await go.exec({ + console.log("Module dot build path:", module.buildPath) + // let goOutput = await execa("mkdir", ["foo" + Math.random()], {cwd: module.buildPath}) + goOutput = await go.exec({ args: buildArgs, - cwd: module.buildPath, + cwd: hotReload ? module.path : module.buildPath, log, env: { CGO_ENABLED: "0", GOOS: "linux", - GOCACHE: resolve(module.buildPath, "cache"), + // GOCACHE: resolve(module.buildPath, "cache"), }, }) } catch (err) { console.log(err.stdout) + status.setState(err.stderr) } + console.log("goOutput:", goOutput.stdout) // if (compress != "") { // await upx.exec({ // args: ["mod", "vendor"], @@ -231,8 +272,13 @@ async function build(params: BuildModuleParams) { const dockerFileBuild = resolve(module.buildPath, defaultDockerfileName) await copy(defaultDockerfilePath, dockerFileBuild) + const scriptName = "myscript.sh" + const scriptPath = resolve(STATIC_DIR, "go-container", scriptName) + const scriptBuild = resolve(module.buildPath, "bin", scriptName) + await copy(scriptPath, scriptBuild) + // if (run != "") { -// let dockerFile = await readFile(dockerFileBuild, "utf8") + // let dockerFile = await readFile(dockerFileBuild, "utf8") // dockerFile = dockerFile.replace(/echo/g, run) // try { // await writeFile(dockerFileBuild, dockerFile, "utf8") @@ -251,19 +297,4 @@ async function build(params: BuildModuleParams) { ) } - // What was this for? - // await copy(resolvedJarPath, resolve(module.buildPath, "app.jar")) - - // Build the container - // await prepareBuild(module, log) - return base!(params) } - -// async function prepareBuild(module: MavenContainerModule, log: LogEntry) { -// // Copy the default Dockerfile to the build directory, if the module doesn't provide one -// // Note: Doing this here so that the build status check works as expected. -// if (module.spec.dockerfile === defaultDockerfileName || !(await containerHelpers.hasDockerfile(module))) { -// log.debug(`Using default Dockerfile`) -// await copy(defaultDockerfilePath, resolve(module.buildPath, defaultDockerfileName)) -// } -// } diff --git a/garden-service/src/plugins/go-container/go.ts b/garden-service/src/plugins/go-container/go.ts index ee575fc735..99017150a8 100644 --- a/garden-service/src/plugins/go-container/go.ts +++ b/garden-service/src/plugins/go-container/go.ts @@ -40,7 +40,6 @@ export const go = new BinaryCmd({ specs: { darwin: macos, linux: penguin, - // Is the "32" here really 32 or is it just the name? win32: windows, }, }) diff --git a/garden-service/static/go-container/go-container.Dockerfile b/garden-service/static/go-container/go-container.Dockerfile index dd360e18cf..43e265a348 100644 --- a/garden-service/static/go-container/go-container.Dockerfile +++ b/garden-service/static/go-container/go-container.Dockerfile @@ -1,9 +1,6 @@ -FROM alpine -RUN apk add entr ca-certificates -RUN mkdir app +FROM alpine:3.10.2 +RUN apk add entr ca-certificates & mkdir app WORKDIR /app -EXPOSE 8080 - COPY bin/ /app/ - -CMD ls binary | entr -r ./binary \ No newline at end of file +# RUN ${EXTRA_RUN} +ENTRYPOINT ["/app/binary"] \ No newline at end of file diff --git a/garden-service/static/go-container/myscript.sh b/garden-service/static/go-container/myscript.sh new file mode 100755 index 0000000000..7bbdc05954 --- /dev/null +++ b/garden-service/static/go-container/myscript.sh @@ -0,0 +1,3 @@ +#/bin/sh +apk add entr +ls binary | entr -r ./binary