diff --git a/Dockerfile b/Dockerfile index a238bf3..690c307 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,35 +1,28 @@ # syntax = docker/dockerfile:experimental FROM --platform=${BUILDPLATFORM} golang:1.16-alpine as builder - # passed by buildkit ARG TARGETOS ARG TARGETARCH - # add CA certificates and TZ for local time RUN apk --update add ca-certificates make git - # Create and change to the app directory. RUN mkdir -p /go/src/app WORKDIR /go/src/app - # Retrieve application dependencies. # This allows the container build to reuse cached dependencies. # Expecting to copy go.mod and if present go.sum. COPY go.mod . COPY go.sum . RUN --mount=type=cache,target=/go/mod go mod download - # Copy local code to the container image. COPY . . - # Build the binary. RUN --mount=type=cache,target=/root/.cache/go-build TARGETOS=${TARGETOS} TARGETARCH=${TARGETARCH} make # final image -# keep it FROM alpine - need to copy secrets-init to target container -FROM --platform=${TARGETPLATFORM} alpine:3.13 - -COPY --from=builder /go/src/app/.bin/secrets-init /usr/local/bin/secrets-init - -CMD ["secrets-init", "--version"] +FROM scratch +# copy the binary to the production image from the builder stage. +COPY --from=builder /go/src/app/.bin/secrets-init /secrets-init +ENTRYPOINT ["/secrets-init"] +CMD ["--version"] diff --git a/Makefile b/Makefile index b6b4195..811bdf9 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ PLATFORMS = darwin linux ARCHITECTURES = amd64 arm64 TARGETOS ?= $(GOOS) TARGETARCH ?= $(GOARCH) -LDFLAGS_VERSION = -X main.Version=$(VERSION) -X main.BuildDate=$(DATE) -X main.GitCommit=$(COMMIT) -X main.GitBranch=$(BRANCH) +LDFLAGS_VERSION = -s -w -X main.Version=$(VERSION) -X main.BuildDate=$(DATE) -X main.GitCommit=$(COMMIT) -X main.GitBranch=$(BRANCH) DOCKER = docker GO = go diff --git a/main.go b/main.go index 2020508..d509e3e 100644 --- a/main.go +++ b/main.go @@ -3,9 +3,11 @@ package main import ( "context" "fmt" + "io" "os" "os/exec" "os/signal" + "path/filepath" "runtime" "secrets-init/pkg/secrets" "secrets-init/pkg/secrets/aws" @@ -41,6 +43,15 @@ func main() { Value: "aws", }, }, + Commands: []*cli.Command{ + { + Name: "copy", + Aliases: []string{"cp"}, + Usage: "copy itself to a destination folder", + ArgsUsage: "destination", + Action: copyCmd, + }, + }, Name: "secrets-init", Usage: "enrich environment variables with secrets from secret manager", Action: mainCmd, @@ -61,6 +72,43 @@ func main() { } } +func copyCmd(c *cli.Context) error { + if c.Args().Len() != 1 { + return fmt.Errorf("must specify copy destination") + } + // full path of current executable + src := os.Args[0] + // destination path + dest := filepath.Join(c.Args().First(), filepath.Base(src)) + // copy file with current file mode flags + sourceFileStat, err := os.Stat(src) + if err != nil { + return err + } + if !sourceFileStat.Mode().IsRegular() { + return fmt.Errorf("%s is not a regular file", src) + } + source, err := os.Open(src) + if err != nil { + return err + } + srcInfo, err := source.Stat() + if err != nil { + return err + } + defer func() { _ = source.Close() }() + destination, err := os.Create(dest) + if err != nil { + return err + } + defer func() { _ = destination.Close() }() + _, err = io.Copy(destination, source) + if err != nil { + return err + } + return destination.Chmod(srcInfo.Mode()) +} + func mainCmd(c *cli.Context) error { // Routine to reap zombies (it's the job of init) ctx, cancel := context.WithCancel(context.Background())