From c450e0805d1ed882f9442ef0beebfe78104bdd94 Mon Sep 17 00:00:00 2001 From: Eoin McAfee Date: Wed, 5 Jan 2022 12:11:44 +0000 Subject: [PATCH 01/10] plugin logic to write card data to publish drone card --- cmd/drone-docker/main.go | 46 ++++++++------ daemon.go | 1 + daemon_win.go | 1 + docker.go | 131 +++++++++++++++++++++++++++++++++++++-- go.mod | 2 + go.sum | 13 +++- 6 files changed, 166 insertions(+), 28 deletions(-) diff --git a/cmd/drone-docker/main.go b/cmd/drone-docker/main.go index 3385bb80..36afbdad 100644 --- a/cmd/drone-docker/main.go +++ b/cmd/drone-docker/main.go @@ -248,6 +248,11 @@ func main() { Usage: "additional host:IP mapping", EnvVar: "PLUGIN_ADD_HOST", }, + cli.StringFlag{ + Name: "drone-card-path", + Usage: "card path location to write to", + EnvVar: "DRONE_CARD_PATH", + }, } if err := app.Run(os.Args); err != nil { @@ -266,27 +271,28 @@ func run(c *cli.Context) error { Email: c.String("docker.email"), Config: c.String("docker.config"), }, + CardPath: c.String("drone-card-path"), Build: docker.Build{ - Remote: c.String("remote.url"), - Name: c.String("commit.sha"), - Dockerfile: c.String("dockerfile"), - Context: c.String("context"), - Tags: c.StringSlice("tags"), - Args: c.StringSlice("args"), - ArgsEnv: c.StringSlice("args-from-env"), - Target: c.String("target"), - Squash: c.Bool("squash"), - Pull: c.BoolT("pull-image"), - CacheFrom: c.StringSlice("cache-from"), - Compress: c.Bool("compress"), - Repo: c.String("repo"), - Labels: c.StringSlice("custom-labels"), - LabelSchema: c.StringSlice("label-schema"), - AutoLabel: c.BoolT("auto-label"), - Link: c.String("link"), - NoCache: c.Bool("no-cache"), - AddHost: c.StringSlice("add-host"), - Quiet: c.Bool("quiet"), + Remote: c.String("remote.url"), + Name: c.String("commit.sha"), + Dockerfile: c.String("dockerfile"), + Context: c.String("context"), + Tags: c.StringSlice("tags"), + Args: c.StringSlice("args"), + ArgsEnv: c.StringSlice("args-from-env"), + Target: c.String("target"), + Squash: c.Bool("squash"), + Pull: c.BoolT("pull-image"), + CacheFrom: c.StringSlice("cache-from"), + Compress: c.Bool("compress"), + Repo: c.String("repo"), + Labels: c.StringSlice("custom-labels"), + LabelSchema: c.StringSlice("label-schema"), + AutoLabel: c.BoolT("auto-label"), + Link: c.String("link"), + NoCache: c.Bool("no-cache"), + AddHost: c.StringSlice("add-host"), + Quiet: c.Bool("quiet"), }, Daemon: docker.Daemon{ Registry: c.String("docker.registry"), diff --git a/daemon.go b/daemon.go index 5976cd1d..26448e16 100644 --- a/daemon.go +++ b/daemon.go @@ -10,6 +10,7 @@ import ( const dockerExe = "/usr/local/bin/docker" const dockerdExe = "/usr/local/bin/dockerd" const dockerHome = "/root/.docker/" +const bashExe = "/bin/sh" func (p Plugin) startDaemon() { cmd := commandDaemon(p.Daemon) diff --git a/daemon_win.go b/daemon_win.go index 77e05438..2e4950c9 100644 --- a/daemon_win.go +++ b/daemon_win.go @@ -5,6 +5,7 @@ package docker const dockerExe = "C:\\bin\\docker.exe" const dockerdExe = "" const dockerHome = "C:\\ProgramData\\docker\\" +const bashExe = "/bin/sh" func (p Plugin) startDaemon() { // this is a no-op on windows diff --git a/docker.go b/docker.go index 9effe4c5..04f679ea 100644 --- a/docker.go +++ b/docker.go @@ -1,6 +1,8 @@ package docker import ( + "encoding/base64" + "encoding/json" "fmt" "io/ioutil" "os" @@ -8,6 +10,10 @@ import ( "path/filepath" "strings" "time" + + "github.com/drone/drone-go/drone" + + "github.com/inhies/go-bytesize" ) type ( @@ -63,16 +69,47 @@ type ( // Plugin defines the Docker plugin parameters. Plugin struct { - Login Login // Docker login configuration - Build Build // Docker build configuration - Daemon Daemon // Docker daemon configuration - Dryrun bool // Docker push is skipped - Cleanup bool // Docker purge is enabled + Login Login // Docker login configuration + Build Build // Docker build configuration + Daemon Daemon // Docker daemon configuration + Dryrun bool // Docker push is skipped + Cleanup bool // Docker purge is enabled + CardPath string // Card path to write file to + } + + Inspect []struct { + ID string `json:"Id"` + RepoTags []string `json:"RepoTags"` + RepoDigests []interface{} `json:"RepoDigests"` + Parent string `json:"Parent"` + Comment string `json:"Comment"` + Created time.Time `json:"Created"` + Container string `json:"Container"` + DockerVersion string `json:"DockerVersion"` + Author string `json:"Author"` + Architecture string `json:"Architecture"` + Os string `json:"Os"` + Size int `json:"Size"` + VirtualSize int `json:"VirtualSize"` + Metadata struct { + LastTagTime time.Time `json:"LastTagTime"` + } `json:"Metadata"` + SizeString string + VirtualSizeString string + Time string } ) +const Esc = "\u001B" + +var ( + prefix = Esc + "]1338;" + suffix = Esc + "]0m" +) + // Exec executes the plugin step func (p Plugin) Exec() error { + //var dockerImageProps Inspect // start the Docker daemon server if !p.Daemon.Disabled { p.startDaemon() @@ -152,7 +189,8 @@ func (p Plugin) Exec() error { cmds = append(cmds, commandTag(p.Build, tag)) // docker tag if p.Dryrun == false { - cmds = append(cmds, commandPush(p.Build, tag)) // docker push + cmds = append(cmds, commandPush(p.Build, tag)) // docker push + cmds = append(cmds, commandInspect(p.Build, tag)) // docker inspect } } @@ -168,6 +206,14 @@ func (p Plugin) Exec() error { trace(cmd) err := cmd.Run() + + // inspect container & post card data + if err == nil && isCommandInspect(cmd.Args) { + err = writeCardFile(p) + if err != nil { + return err + } + } if err != nil && isCommandPull(cmd.Args) { fmt.Printf("Could not pull cache-from image %s. Ignoring...\n", cmd.Args[2]) } else if err != nil && isCommandPrune(cmd.Args) { @@ -182,6 +228,53 @@ func (p Plugin) Exec() error { return nil } +func writeCardFile(p Plugin) error { + card := drone.CardInput{ + Schema: "https://harness.github.io/card-templates/drone-docker.json", + } + // read docker inspect output + data, err := ioutil.ReadFile("/tmp/output.json") + if err != nil { + return err + } + + inspect := Inspect{} + err = json.Unmarshal(data, &inspect) + if err != nil { + fmt.Println(err) + return err + } + insp := inspect[0] + insp.SizeString = fmt.Sprint(bytesize.New(float64(insp.Size))) + insp.VirtualSizeString = fmt.Sprint(bytesize.New(float64(insp.VirtualSize))) + insp.Time = fmt.Sprint(insp.Metadata.LastTagTime.Format(time.RFC3339)) + if err != nil { + fmt.Println(err) + } + result, err := json.Marshal(insp) + if err != nil { + fmt.Println(err) + return err + } + card.Data = result + file, err := json.Marshal(card) + if err != nil { + fmt.Println(err) + return err + } + // support both writing to file location & encoded to logs + path := p.CardPath + switch { + case path == "/dev/stdout": + // !important - new line required otherwise TrimSuffix in runner won't work + sEnc := fmt.Sprintf("%s%s%s%s", prefix, base64.StdEncoding.EncodeToString(file), suffix, "\n") + err = ioutil.WriteFile("/dev/stdout", []byte(sEnc), 0644) + case path != "": + ioutil.WriteFile(path, file, 0644) + } + return nil +} + // helper function to create the docker login command. func commandLogin(login Login) *exec.Cmd { if login.Email != "" { @@ -204,6 +297,17 @@ func commandPull(repo string) *exec.Cmd { return exec.Command(dockerExe, "pull", repo) } +func commandInspect(build Build, tag string) *exec.Cmd { + target := fmt.Sprintf("%s:%s", build.Name, tag) + args := []string{ + "docker inspect", + } + args = append(args, target) + args = append(args, "> /tmp/output.json") + + return exec.Command(bashExe, "-c", strings.Join(args, " ")) +} + func commandLoginEmail(login Login) *exec.Cmd { return exec.Command( dockerExe, "login", @@ -411,8 +515,23 @@ func commandRmi(tag string) *exec.Cmd { return exec.Command(dockerExe, "rmi", tag) } +// helper to check if args match "docker inspect" +func isCommandInspect(args []string) bool { + return args[0] == "/bin/sh" +} + // trace writes each command to stdout with the command wrapped in an xml // tag so that it can be extracted and displayed in the logs. func trace(cmd *exec.Cmd) { fmt.Fprintf(os.Stdout, "+ %s\n", strings.Join(cmd.Args, " ")) } + +func getenv(key ...string) (s string) { + for _, k := range key { + s = os.Getenv(k) + if s != "" { + return + } + } + return +} diff --git a/go.mod b/go.mod index 36080ecc..9a962d61 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,8 @@ module github.com/drone-plugins/drone-docker require ( github.com/aws/aws-sdk-go v1.26.7 github.com/coreos/go-semver v0.2.0 + github.com/drone/drone-go v1.7.1 + github.com/inhies/go-bytesize v0.0.0-20210819104631-275770b98743 github.com/joho/godotenv v1.3.0 github.com/sirupsen/logrus v1.3.0 github.com/urfave/cli v1.22.2 diff --git a/go.sum b/go.sum index e684144e..377d1ac8 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e/go.mod h1:Xa6lInWHNQnuWoF0YPSsx+INFA9qk7/7pTjwb3PInkY= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/aws/aws-sdk-go v1.26.7 h1:ObjEnmzvSdYy8KVd3me7v/UMyCn81inLy2SyoIPoBkg= github.com/aws/aws-sdk-go v1.26.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= @@ -7,12 +8,22 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSY github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/drone/drone-go v1.7.1 h1:ZX+3Rs8YHUSUQ5mkuMLmm1zr1ttiiE2YGNxF3AnyDKw= +github.com/drone/drone-go v1.7.1/go.mod h1:fxCf9jAnXDZV1yDr0ckTuWd1intvcQwfJmTRpTZ1mXg= +github.com/go-playground/ansi/v3 v3.0.0 h1:TXexAx1sXuL/N/cqV472ffRdkoiqPA3LeKMXCoz8t4Y= +github.com/go-playground/ansi/v3 v3.0.0/go.mod h1:btm11Vjtjy20mZiJwufDvdVAVxjLuYFDu164b83ekBs= +github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/inhies/go-bytesize v0.0.0-20210819104631-275770b98743 h1:X3Xxno5Ji8idrNiUoFc7QyXpqhSYlDRYQmc7mlpMBzU= +github.com/inhies/go-bytesize v0.0.0-20210819104631-275770b98743/go.mod h1:KrtyD5PFj++GKkFS/7/RRrfnRhAMGQwy75GLCHWrCNs= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/pborman/ansi v1.0.0 h1:OqjHMhvlSuCCV5JT07yqPuJPQzQl+WXsiZ14gZsqOrQ= +github.com/pborman/ansi v1.0.0/go.mod h1:SgWzwMAx1X/Ez7i90VqF8LRiQtx52pWDiQP+x3iGnzw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= @@ -24,8 +35,6 @@ github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I= From 1daeac9a99b5a8b596debbdd99d856be7cacd9d1 Mon Sep 17 00:00:00 2001 From: eoinmcafee00 Date: Mon, 10 Jan 2022 10:39:19 +0000 Subject: [PATCH 02/10] setup card template for github pages --- templates/card.json | 118 +++++++++++++++++++++++++++++++++++++++++++ templates/index.json | 0 2 files changed, 118 insertions(+) create mode 100644 templates/card.json create mode 100644 templates/index.json diff --git a/templates/card.json b/templates/card.json new file mode 100644 index 00000000..de02706f --- /dev/null +++ b/templates/card.json @@ -0,0 +1,118 @@ +{ + "type": "AdaptiveCard", + "body": [ + { + "type": "ColumnSet", + "columns": [ + { + "type": "Column", + "items": [ + { + "type": "Image", + "url": "https://d36jcksde1wxzq.cloudfront.net/be7833db9bddb4494d2a7c3dd659199a.png", + "size": "Medium" + } + ], + "width": "auto" + }, + { + "type": "Column", + "items": [ + { + "type": "TextBlock", + "text": "${RepoTags[0]}", + "size": "Medium" + }, + { + "type": "TextBlock", + "text": "DIGEST: ${RepoDigests[0]}", + "wrap": true, + "size": "Small", + "weight": "Lighter", + "isSubtle": true, + "spacing": "Small" + }, + { + "type": "ColumnSet", + "columns": [ + { + "type": "Column", + "items": [ + { + "type": "TextBlock", + "weight": "Lighter", + "text": "OS/ARCH", + "wrap": true, + "size": "Small", + "isSubtle": true, + "spacing": "Medium" + }, + { + "type": "TextBlock", + "text": "${OS}/${Architecture}", + "wrap": true, + "size": "Small", + "spacing": "Small" + } + ], + "separator": true, + "width": "auto" + }, + { + "type": "Column", + "items": [ + { + "type": "TextBlock", + "weight": "Lighter", + "text": "SIZE", + "wrap": true, + "size": "Small", + "isSubtle": true + }, + { + "type": "TextBlock", + "spacing": "Small", + "text": "${SizeString}", + "wrap": true, + "size": "Small" + } + ], + "width": "auto", + "separator": true, + "spacing": "Medium" + }, + { + "type": "Column", + "items": [ + { + "type": "TextBlock", + "weight": "Lighter", + "text": "LAST PUSHED", + "wrap": true, + "size": "Small", + "isSubtle": true + }, + { + "type": "TextBlock", + "spacing": "Small", + "text": "{{DATE(${Time})}} - {{TIME(${Time})}}", + "wrap": true, + "size": "Small" + } + ], + "width": "auto", + "separator": true, + "spacing": "Medium" + } + ], + "style": "default" + } + ], + "width": "stretch" + } + ] + } + ], + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "version": "1.0" +} \ No newline at end of file diff --git a/templates/index.json b/templates/index.json new file mode 100644 index 00000000..e69de29b From d99f7c8b5a44ce9a613863c473f2c5d7dca2fab1 Mon Sep 17 00:00:00 2001 From: eoinmcafee00 Date: Mon, 10 Jan 2022 10:46:06 +0000 Subject: [PATCH 03/10] rename to docs --- {templates => docs}/card.json | 0 {templates => docs}/index.json | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {templates => docs}/card.json (100%) rename {templates => docs}/index.json (100%) diff --git a/templates/card.json b/docs/card.json similarity index 100% rename from templates/card.json rename to docs/card.json diff --git a/templates/index.json b/docs/index.json similarity index 100% rename from templates/index.json rename to docs/index.json From 815fd1ddb55adb1ebfa7c9a08767d9262396f3e8 Mon Sep 17 00:00:00 2001 From: eoinmcafee00 Date: Mon, 10 Jan 2022 10:48:52 +0000 Subject: [PATCH 04/10] update template url to new location --- docker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker.go b/docker.go index 04f679ea..24f5dbc0 100644 --- a/docker.go +++ b/docker.go @@ -230,7 +230,7 @@ func (p Plugin) Exec() error { func writeCardFile(p Plugin) error { card := drone.CardInput{ - Schema: "https://harness.github.io/card-templates/drone-docker.json", + Schema: "https://drone-plugins.github.io/drone-docker/card.json", } // read docker inspect output data, err := ioutil.ReadFile("/tmp/output.json") From d43a4703a3011a160ce633a939c01d7e2a3799d7 Mon Sep 17 00:00:00 2001 From: eoinmcafee00 Date: Mon, 10 Jan 2022 10:50:57 +0000 Subject: [PATCH 05/10] merge master --- go.sum | 4 ---- 1 file changed, 4 deletions(-) diff --git a/go.sum b/go.sum index 377d1ac8..0564b646 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/drone/drone-go v1.7.1 h1:ZX+3Rs8YHUSUQ5mkuMLmm1zr1ttiiE2YGNxF3AnyDKw= github.com/drone/drone-go v1.7.1/go.mod h1:fxCf9jAnXDZV1yDr0ckTuWd1intvcQwfJmTRpTZ1mXg= -github.com/go-playground/ansi/v3 v3.0.0 h1:TXexAx1sXuL/N/cqV472ffRdkoiqPA3LeKMXCoz8t4Y= -github.com/go-playground/ansi/v3 v3.0.0/go.mod h1:btm11Vjtjy20mZiJwufDvdVAVxjLuYFDu164b83ekBs= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/inhies/go-bytesize v0.0.0-20210819104631-275770b98743 h1:X3Xxno5Ji8idrNiUoFc7QyXpqhSYlDRYQmc7mlpMBzU= @@ -22,8 +20,6 @@ github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/pborman/ansi v1.0.0 h1:OqjHMhvlSuCCV5JT07yqPuJPQzQl+WXsiZ14gZsqOrQ= -github.com/pborman/ansi v1.0.0/go.mod h1:SgWzwMAx1X/Ez7i90VqF8LRiQtx52pWDiQP+x3iGnzw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= From 12453aebe3f938c58d037e4805161ab2586c00f2 Mon Sep 17 00:00:00 2001 From: eoinmcafee00 Date: Wed, 12 Jan 2022 16:14:22 +0000 Subject: [PATCH 06/10] tech qa refactor --- docker.go | 110 ++++++++++++++++++++++++------------------------------ 1 file changed, 49 insertions(+), 61 deletions(-) diff --git a/docker.go b/docker.go index 24f5dbc0..bec1c940 100644 --- a/docker.go +++ b/docker.go @@ -4,6 +4,7 @@ import ( "encoding/base64" "encoding/json" "fmt" + "io" "io/ioutil" "os" "os/exec" @@ -189,8 +190,7 @@ func (p Plugin) Exec() error { cmds = append(cmds, commandTag(p.Build, tag)) // docker tag if p.Dryrun == false { - cmds = append(cmds, commandPush(p.Build, tag)) // docker push - cmds = append(cmds, commandInspect(p.Build, tag)) // docker inspect + cmds = append(cmds, commandPush(p.Build, tag)) // docker push } } @@ -206,14 +206,6 @@ func (p Plugin) Exec() error { trace(cmd) err := cmd.Run() - - // inspect container & post card data - if err == nil && isCommandInspect(cmd.Args) { - err = writeCardFile(p) - if err != nil { - return err - } - } if err != nil && isCommandPull(cmd.Args) { fmt.Printf("Could not pull cache-from image %s. Ignoring...\n", cmd.Args[2]) } else if err != nil && isCommandPrune(cmd.Args) { @@ -224,55 +216,58 @@ func (p Plugin) Exec() error { return err } } - + writeDockerCard(p) return nil } -func writeCardFile(p Plugin) error { - card := drone.CardInput{ - Schema: "https://drone-plugins.github.io/drone-docker/card.json", - } - // read docker inspect output - data, err := ioutil.ReadFile("/tmp/output.json") - if err != nil { - return err - } - - inspect := Inspect{} - err = json.Unmarshal(data, &inspect) - if err != nil { - fmt.Println(err) - return err - } - insp := inspect[0] - insp.SizeString = fmt.Sprint(bytesize.New(float64(insp.Size))) - insp.VirtualSizeString = fmt.Sprint(bytesize.New(float64(insp.VirtualSize))) - insp.Time = fmt.Sprint(insp.Metadata.LastTagTime.Format(time.RFC3339)) - if err != nil { - fmt.Println(err) - } - result, err := json.Marshal(insp) - if err != nil { - fmt.Println(err) - return err - } - card.Data = result - file, err := json.Marshal(card) - if err != nil { - fmt.Println(err) - return err - } - // support both writing to file location & encoded to logs - path := p.CardPath +func writeDockerCard(p Plugin) { + // run docker inspect + for _, tag := range p.Build.Tags { + card := drone.CardInput{ + Schema: "https://drone-plugins.github.io/drone-docker/card.json", + } + cmd := commandInspect(p.Build, tag) + raw, err := cmd.CombinedOutput() + if err != nil { + fmt.Println(err) + } + inspect := Inspect{} + err = json.Unmarshal(raw, &inspect) + if err != nil { + fmt.Println(err) + } + insp := inspect[0] + insp.SizeString = fmt.Sprint(bytesize.New(float64(insp.Size))) + insp.VirtualSizeString = fmt.Sprint(bytesize.New(float64(insp.VirtualSize))) + insp.Time = fmt.Sprint(insp.Metadata.LastTagTime.Format(time.RFC3339)) + // create card structure + result, err := json.Marshal(insp) + if err != nil { + fmt.Println(err) + } + card.Data = result + writeCard(p.CardPath, card) + } +} + +func writeCard(path string, card interface{}) { + data, _ := json.Marshal(card) switch { case path == "/dev/stdout": - // !important - new line required otherwise TrimSuffix in runner won't work - sEnc := fmt.Sprintf("%s%s%s%s", prefix, base64.StdEncoding.EncodeToString(file), suffix, "\n") - err = ioutil.WriteFile("/dev/stdout", []byte(sEnc), 0644) + writeCardTo(os.Stdout, data) + case path == "/dev/stderr": + writeCardTo(os.Stderr, data) case path != "": - ioutil.WriteFile(path, file, 0644) + ioutil.WriteFile(path, data, 0644) } - return nil +} + +func writeCardTo(out io.Writer, data []byte) { + encoded := base64.StdEncoding.EncodeToString(data) + io.WriteString(out, "\u001B]1338;") + io.WriteString(out, encoded) + io.WriteString(out, "\u001B]0m") + io.WriteString(out, "\n") } // helper function to create the docker login command. @@ -299,13 +294,7 @@ func commandPull(repo string) *exec.Cmd { func commandInspect(build Build, tag string) *exec.Cmd { target := fmt.Sprintf("%s:%s", build.Name, tag) - args := []string{ - "docker inspect", - } - args = append(args, target) - args = append(args, "> /tmp/output.json") - - return exec.Command(bashExe, "-c", strings.Join(args, " ")) + return exec.Command(dockerExe, "inspect", target) } func commandLoginEmail(login Login) *exec.Cmd { @@ -336,7 +325,6 @@ func commandBuild(build Build) *exec.Cmd { "-f", build.Dockerfile, "-t", build.Name, } - args = append(args, build.Context) if build.Squash { args = append(args, "--squash") @@ -517,7 +505,7 @@ func commandRmi(tag string) *exec.Cmd { // helper to check if args match "docker inspect" func isCommandInspect(args []string) bool { - return args[0] == "/bin/sh" + return args[1] == "inspect" } // trace writes each command to stdout with the command wrapped in an xml From 6551ee1d79e4c2577f5f1f95762b7991c5e2b436 Mon Sep 17 00:00:00 2001 From: eoinmcafee00 Date: Wed, 12 Jan 2022 16:18:11 +0000 Subject: [PATCH 07/10] remove unused code --- daemon.go | 2 +- daemon_win.go | 2 +- docker.go | 22 ---------------------- 3 files changed, 2 insertions(+), 24 deletions(-) diff --git a/daemon.go b/daemon.go index 26448e16..2271257c 100644 --- a/daemon.go +++ b/daemon.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package docker @@ -10,7 +11,6 @@ import ( const dockerExe = "/usr/local/bin/docker" const dockerdExe = "/usr/local/bin/dockerd" const dockerHome = "/root/.docker/" -const bashExe = "/bin/sh" func (p Plugin) startDaemon() { cmd := commandDaemon(p.Daemon) diff --git a/daemon_win.go b/daemon_win.go index 2e4950c9..db6c160d 100644 --- a/daemon_win.go +++ b/daemon_win.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package docker @@ -5,7 +6,6 @@ package docker const dockerExe = "C:\\bin\\docker.exe" const dockerdExe = "" const dockerHome = "C:\\ProgramData\\docker\\" -const bashExe = "/bin/sh" func (p Plugin) startDaemon() { // this is a no-op on windows diff --git a/docker.go b/docker.go index bec1c940..9be266ed 100644 --- a/docker.go +++ b/docker.go @@ -101,13 +101,6 @@ type ( } ) -const Esc = "\u001B" - -var ( - prefix = Esc + "]1338;" - suffix = Esc + "]0m" -) - // Exec executes the plugin step func (p Plugin) Exec() error { //var dockerImageProps Inspect @@ -503,23 +496,8 @@ func commandRmi(tag string) *exec.Cmd { return exec.Command(dockerExe, "rmi", tag) } -// helper to check if args match "docker inspect" -func isCommandInspect(args []string) bool { - return args[1] == "inspect" -} - // trace writes each command to stdout with the command wrapped in an xml // tag so that it can be extracted and displayed in the logs. func trace(cmd *exec.Cmd) { fmt.Fprintf(os.Stdout, "+ %s\n", strings.Join(cmd.Args, " ")) } - -func getenv(key ...string) (s string) { - for _, k := range key { - s = os.Getenv(k) - if s != "" { - return - } - } - return -} From 0836ffd3b7f133fd0b17a3f61205e8c3a3a98f69 Mon Sep 17 00:00:00 2001 From: eoinmcafee00 Date: Wed, 12 Jan 2022 16:18:50 +0000 Subject: [PATCH 08/10] reset files back to master --- daemon.go | 1 - daemon_win.go | 1 - 2 files changed, 2 deletions(-) diff --git a/daemon.go b/daemon.go index 2271257c..5976cd1d 100644 --- a/daemon.go +++ b/daemon.go @@ -1,4 +1,3 @@ -//go:build !windows // +build !windows package docker diff --git a/daemon_win.go b/daemon_win.go index db6c160d..77e05438 100644 --- a/daemon_win.go +++ b/daemon_win.go @@ -1,4 +1,3 @@ -//go:build windows // +build windows package docker From 3c69ace106977960ee78902173814dc6b7b72ecc Mon Sep 17 00:00:00 2001 From: eoinmcafee00 Date: Wed, 12 Jan 2022 16:50:31 +0000 Subject: [PATCH 09/10] more refactor based on Brads suggestions --- card.go | 62 +++++++++++++++++++++++++++++++++++++++++ docker.go | 83 ++++++++++++------------------------------------------- 2 files changed, 80 insertions(+), 65 deletions(-) create mode 100644 card.go diff --git a/card.go b/card.go new file mode 100644 index 00000000..6dffe55f --- /dev/null +++ b/card.go @@ -0,0 +1,62 @@ +package docker + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "os" + "os/exec" + "time" + + "github.com/drone/drone-go/drone" + "github.com/inhies/go-bytesize" +) + +func (p Plugin) writeCard() error { + cmd := exec.Command("docker", "inspect", p.Build.Name) + data, err := cmd.CombinedOutput() + if err != nil { + return err + } + + out := Inspect{} + if err := json.Unmarshal(data, &out); err != nil { + return err + } + + inspect := out[0] + inspect.SizeString = fmt.Sprint(bytesize.New(float64(inspect.Size))) + inspect.VirtualSizeString = fmt.Sprint(bytesize.New(float64(inspect.VirtualSize))) + inspect.Time = fmt.Sprint(inspect.Metadata.LastTagTime.Format(time.RFC3339)) + cardData, _ := json.Marshal(inspect) + + card := drone.CardInput{ + Schema: "https://drone-plugins.github.io/drone-docker/card.json", + Data: cardData, + } + + writeCard(p.CardPath, &card) + return nil +} + +func writeCard(path string, card interface{}) { + data, _ := json.Marshal(card) + switch { + case path == "/dev/stdout": + writeCardTo(os.Stdout, data) + case path == "/dev/stderr": + writeCardTo(os.Stderr, data) + case path != "": + ioutil.WriteFile(path, data, 0644) + } +} + +func writeCardTo(out io.Writer, data []byte) { + encoded := base64.StdEncoding.EncodeToString(data) + io.WriteString(out, "\u001B]1338;") + io.WriteString(out, encoded) + io.WriteString(out, "\u001B]0m") + io.WriteString(out, "\n") +} diff --git a/docker.go b/docker.go index 9be266ed..0735aab6 100644 --- a/docker.go +++ b/docker.go @@ -1,20 +1,13 @@ package docker import ( - "encoding/base64" - "encoding/json" "fmt" - "io" "io/ioutil" "os" "os/exec" "path/filepath" "strings" "time" - - "github.com/drone/drone-go/drone" - - "github.com/inhies/go-bytesize" ) type ( @@ -103,7 +96,6 @@ type ( // Exec executes the plugin step func (p Plugin) Exec() error { - //var dockerImageProps Inspect // start the Docker daemon server if !p.Daemon.Disabled { p.startDaemon() @@ -187,11 +179,6 @@ func (p Plugin) Exec() error { } } - if p.Cleanup { - cmds = append(cmds, commandRmi(p.Build.Name)) // docker rmi - cmds = append(cmds, commandPrune()) // docker system prune -f - } - // execute all commands in batch mode. for _, cmd := range cmds { cmd.Stdout = os.Stdout @@ -209,58 +196,28 @@ func (p Plugin) Exec() error { return err } } - writeDockerCard(p) - return nil -} -func writeDockerCard(p Plugin) { - // run docker inspect - for _, tag := range p.Build.Tags { - card := drone.CardInput{ - Schema: "https://drone-plugins.github.io/drone-docker/card.json", - } - cmd := commandInspect(p.Build, tag) - raw, err := cmd.CombinedOutput() - if err != nil { - fmt.Println(err) - } - inspect := Inspect{} - err = json.Unmarshal(raw, &inspect) - if err != nil { - fmt.Println(err) - } - insp := inspect[0] - insp.SizeString = fmt.Sprint(bytesize.New(float64(insp.Size))) - insp.VirtualSizeString = fmt.Sprint(bytesize.New(float64(insp.VirtualSize))) - insp.Time = fmt.Sprint(insp.Metadata.LastTagTime.Format(time.RFC3339)) - // create card structure - result, err := json.Marshal(insp) - if err != nil { - fmt.Println(err) - } - card.Data = result - writeCard(p.CardPath, card) + // output the adaptive card + if err := p.writeCard(); err != nil { + fmt.Printf("Could not create adaptive card. %s\n", err) } -} -func writeCard(path string, card interface{}) { - data, _ := json.Marshal(card) - switch { - case path == "/dev/stdout": - writeCardTo(os.Stdout, data) - case path == "/dev/stderr": - writeCardTo(os.Stderr, data) - case path != "": - ioutil.WriteFile(path, data, 0644) + // execute cleanup routines in batch mode + if p.Cleanup { + // clear the slice + cmds = nil + + cmds = append(cmds, commandRmi(p.Build.Name)) // docker rmi + cmds = append(cmds, commandPrune()) // docker system prune -f + + for _, cmd := range cmds { + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + trace(cmd) + } } -} -func writeCardTo(out io.Writer, data []byte) { - encoded := base64.StdEncoding.EncodeToString(data) - io.WriteString(out, "\u001B]1338;") - io.WriteString(out, encoded) - io.WriteString(out, "\u001B]0m") - io.WriteString(out, "\n") + return nil } // helper function to create the docker login command. @@ -285,11 +242,6 @@ func commandPull(repo string) *exec.Cmd { return exec.Command(dockerExe, "pull", repo) } -func commandInspect(build Build, tag string) *exec.Cmd { - target := fmt.Sprintf("%s:%s", build.Name, tag) - return exec.Command(dockerExe, "inspect", target) -} - func commandLoginEmail(login Login) *exec.Cmd { return exec.Command( dockerExe, "login", @@ -318,6 +270,7 @@ func commandBuild(build Build) *exec.Cmd { "-f", build.Dockerfile, "-t", build.Name, } + args = append(args, build.Context) if build.Squash { args = append(args, "--squash") From b527f3ac64db5e688b458a7368d9f7b08cbc2b1c Mon Sep 17 00:00:00 2001 From: eoinmcafee00 Date: Wed, 12 Jan 2022 16:51:09 +0000 Subject: [PATCH 10/10] imports --- card.go | 1 + 1 file changed, 1 insertion(+) diff --git a/card.go b/card.go index 6dffe55f..e9bd76a5 100644 --- a/card.go +++ b/card.go @@ -11,6 +11,7 @@ import ( "time" "github.com/drone/drone-go/drone" + "github.com/inhies/go-bytesize" )