From 8241fb3e13e0c83b02cb9b97bafac15750fb5212 Mon Sep 17 00:00:00 2001 From: Erno Aapa Date: Mon, 28 Jun 2021 15:44:19 +0300 Subject: [PATCH] Add support for JSON output format To use the outdated information in other systems, provide optional JSON output format. --- cmd/outdated/cli/root.go | 86 ++++++++++++++++++++++++++++++---------- pkg/logger/json.go | 12 ++++++ 2 files changed, 78 insertions(+), 20 deletions(-) create mode 100644 pkg/logger/json.go diff --git a/cmd/outdated/cli/root.go b/cmd/outdated/cli/root.go index 6e80984..aaf2f6f 100644 --- a/cmd/outdated/cli/root.go +++ b/cmd/outdated/cli/root.go @@ -1,6 +1,7 @@ package cli import ( + "encoding/json" "fmt" "os" "strings" @@ -31,7 +32,6 @@ func RootCmd() *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { v := viper.GetViper() log := logger.NewLogger() - log.Info("") o := outdated.Outdated{} @@ -69,26 +69,14 @@ func RootCmd() *cobra.Command { } finishedCh <- true - head, imageColumnWidth, tagColumnWidth := headerLine(images) - log.Header(head) - - for _, image := range images { - log.StartImageLine(runningImage(image, imageColumnWidth, tagColumnWidth)) - checkResult, err := o.ParseImage(image.Image, image.PullableImage) - if err != nil { - log.FinalizeImageLineWithError(erroredImage(image, checkResult, imageColumnWidth, tagColumnWidth)) - } else { - if checkResult.VersionsBehind != -1 { - log.FinalizeImageLine(checkResult.VersionsBehind, completedImage(image, checkResult, imageColumnWidth, tagColumnWidth)) - } else { - log.FinalizeImageLineWithError(erroredImage(image, checkResult, imageColumnWidth, tagColumnWidth)) - } - } + switch output := v.GetString("output"); output { + case "text": + return printInText(log, o, images) + case "json": + return printInJSON(log, o, images) + default: + return fmt.Errorf("Invalid output format %s, should be one of [text, json]", output) } - - log.Info("") - - return nil }, } @@ -98,10 +86,68 @@ func RootCmd() *cobra.Command { KubernetesConfigFlags.AddFlags(cmd.Flags()) cmd.Flags().StringSlice("ignore-ns", []string{}, "optional list of namespaces to exclude from searching") + cmd.Flags().String("output", "text", "Output format. One of: text|json") viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) return cmd } +func printInText(log *logger.Logger, o outdated.Outdated, images []outdated.RunningImage) error { + log.Info("") + + head, imageColumnWidth, tagColumnWidth := headerLine(images) + log.Header(head) + + for _, image := range images { + log.StartImageLine(runningImage(image, imageColumnWidth, tagColumnWidth)) + checkResult, err := o.ParseImage(image.Image, image.PullableImage) + if err != nil { + log.FinalizeImageLineWithError(erroredImage(image, checkResult, imageColumnWidth, tagColumnWidth)) + } else { + if checkResult.VersionsBehind != -1 { + log.FinalizeImageLine(checkResult.VersionsBehind, completedImage(image, checkResult, imageColumnWidth, tagColumnWidth)) + } else { + log.FinalizeImageLineWithError(erroredImage(image, checkResult, imageColumnWidth, tagColumnWidth)) + } + } + } + + log.Info("") + + return nil +} + +func printInJSON(log *logger.Logger, o outdated.Outdated, images []outdated.RunningImage) error { + results := []logger.JSONResult{} + + for _, image := range images { + repo, imgName, tag, err := outdated.ParseImageName(image.Image) + result := logger.JSONResult{ + Repo: repo, + Image: imgName, + Tag: tag, + } + if err != nil { + return err + } + + checkResult, err := o.ParseImage(image.Image, image.PullableImage) + if err != nil { + result.Error = &checkResult.CheckError + } else { + result.LatestVersion = checkResult.LatestVersion + result.VersionsBehind = checkResult.VersionsBehind + } + results = append(results, result) + } + + d, err := json.Marshal(results) + if err != nil { + return err + } + log.Info(string(d)) + return nil +} + func InitAndExecute() { if err := RootCmd().Execute(); err != nil { fmt.Println(err) diff --git a/pkg/logger/json.go b/pkg/logger/json.go new file mode 100644 index 0000000..bbfc20a --- /dev/null +++ b/pkg/logger/json.go @@ -0,0 +1,12 @@ +package logger + +type JSONResult struct { + Repo string `json:"repository"` + Image string `json:"image"` + Tag string `json:"tag"` + + LatestVersion string `json:"latestVersion"` + VersionsBehind int64 `json:"versionsBehind"` + + Error *string `json:"error,omitempty"` +}