diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..c41698c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +docker-stats-on-exit-shim + +# Vim swap files +.*.swp +.gitignore +.travis.yml +Dockerfile \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ee5cf0c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM golang:1.12 as builder +RUN go get -u github.com/golang/dep/... + +WORKDIR $GOPATH/src/github.com/delcypher/docker-stats-on-exit-shim + +COPY Gopkg.toml . +COPY main.go . + +RUN dep ensure + +RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o /docker-stats-on-exit-shim + +FROM alpine:latest + +WORKDIR / + +COPY --from=builder /docker-stats-on-exit-shim . + +ENTRYPOINT ["/docker-stats-on-exit-shim"] + +CMD ["sleep", "1"] diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 0000000..628823f --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,4 @@ + +[[override]] + name = "github.com/opencontainers/runc" + revision = "a2a6e82" \ No newline at end of file diff --git a/README.md b/README.md index e926c3f..9b15ffc 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,23 @@ real command by waiting for it to exit and then querying the active Cgroup subsy to gather their statistics. It dumps these statistics to a file as JSON and then exits with the exit code of the real command. -## Example +## Environment variables +- `STATS_OUTPUT_FILE=/dev/stdout` file path you want your output to be saved to (Default /dev/stdout) +- `STATS_OUTPUT_PREFIX=` any prefix you want to add before stats output (Default blank) +- `STATS_OUTPUT_MINIFIED=false` true|false (Default true) +## Example +Dockerfile +``` +COPY --from=hasnat/docker-stats-on-exit-shim /docker-stats-on-exit-shim . +ENTRYPOINT ["/docker-stats-on-exit-shim"] +CMD ["sleep", "1"] +``` +Example Run ```bash -$ docker run --rm -ti -v`pwd`:/tmp/:rw ubuntu /tmp/docker-stats-on-exit-shim /tmp/output.json /bin/sleep 1 -$ cat output.json +$ docker run --rm -ti hasnat/docker-stats-on-exit-shim /bin/sleep 1 ``` +Output example ```json { "wall_time": 1000765975, @@ -53,10 +64,7 @@ $ cat output.json mkdir -p src/github.com/delcypher export GOPATH=`pwd` cd src/github.com/delcypher -git clone git@github.com:delcypher/docker-stats-on-exit-shim.git -cd docker-stats-on-exit-shim -git submodule init && git submodule update -go get . +dep ensure go build ``` diff --git a/main.go b/main.go index 1326d22..206649a 100644 --- a/main.go +++ b/main.go @@ -21,15 +21,15 @@ import ( "os/signal" "syscall" "time" + "strconv" cgroups "github.com/opencontainers/runc/libcontainer/cgroups" cgroups_fs "github.com/opencontainers/runc/libcontainer/cgroups/fs" ) func printUsage() { - fmt.Printf("%s [arg...]\n", os.Args[0]) - fmt.Println("") + fmt.Printf("%s [arg...]\n", os.Args[0]) + fmt.Println("environment variables STATS_OUTPUT_FILE=/dev/stdout STATS_OUTPUT_MINIFIED=false STATS_OUTPUT_PREFIX=") fmt.Println("Runs and on termination outputs cgroup usage information") - fmt.Println("as JSON to ") } type Stats struct { @@ -62,16 +62,24 @@ func fail(template string, args ...interface{}) { os.Exit(FailExitCode) } +func getEnv(key, defaultValue string) string { + value := os.Getenv(key) + if len(value) == 0 { + return defaultValue + } + return value +} + func main() { exitCode := 0; - if len(os.Args) < 3 { + if len(os.Args) < 2 { printUsage() os.Exit(1) } // Open file for writing stats - f, err := os.Create(os.Args[1]) + f, err := os.Create(getEnv("STATS_OUTPUT_FILE", "/dev/stdout")) if err != nil { fail("Failed to create stats file %s: %s\n", os.Args[1], err) } @@ -109,7 +117,7 @@ func main() { // Run the subproccess - cmd := exec.Command(os.Args[2], os.Args[3:]...) + cmd := exec.Command(os.Args[1], os.Args[2:]...) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr @@ -168,10 +176,21 @@ func main() { } //fmt.Printf("Stats: %+v", combinedStats) - statsAsBytes, err := json.MarshalIndent(&combinedStats, "", " ") + statsPrefix := getEnv("STATS_OUTPUT_PREFIX", "") + minified := false + minified, _ = strconv.ParseBool(getEnv("STATS_OUTPUT_MINIFIED", "false")) + var statsAsBytes []byte + if minified { + statsAsBytes, err = json.Marshal(&combinedStats) + } else { + statsAsBytes, err = json.MarshalIndent(&combinedStats, "", " ") + } + if err != nil { fail("Failed to serialize stats to JSON: %s\n", err) } + + _, err = f.Write([]byte(statsPrefix)) _, err = f.Write(statsAsBytes) if err != nil { fail("Failed to write stats to file: %s\n", err) diff --git a/vendor/github.com/opencontainers/runc b/vendor/github.com/opencontainers/runc deleted file mode 160000 index a2a6e82..0000000 --- a/vendor/github.com/opencontainers/runc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a2a6e828a9cafd11fb02b3589833a77c7af50b2f