Skip to content

Commit

Permalink
Add JSON format to status subcommand (#1655)
Browse files Browse the repository at this point in the history
Add a `--format json` option to elastic-package status, that shows
the same information but in JSON format.
  • Loading branch information
jsoriano authored Feb 5, 2024
1 parent a567a70 commit a75fd6f
Show file tree
Hide file tree
Showing 12 changed files with 341 additions and 1 deletion.
110 changes: 109 additions & 1 deletion cmd/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package cmd

import (
"encoding/json"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -37,6 +38,9 @@ const (
categoriesParameter = "categories"
elasticsearchSubscriptionParameter = "elastic.subscription"
serverlessProjectTypesParameter = "serverless.project_types"

statusTableFormat = "table"
statusJSONFormat = "json"
)

var (
Expand All @@ -50,6 +54,11 @@ var (
elasticsearchSubscriptionParameter,
serverlessProjectTypesParameter,
}

availableFormatsParameters = []string{
statusTableFormat,
statusJSONFormat,
}
)

func setupStatusCommand() *cobraext.Command {
Expand All @@ -63,6 +72,7 @@ func setupStatusCommand() *cobraext.Command {
cmd.Flags().BoolP(cobraext.ShowAllFlagName, "a", false, cobraext.ShowAllFlagDescription)
cmd.Flags().String(cobraext.StatusKibanaVersionFlagName, "", cobraext.StatusKibanaVersionFlagDescription)
cmd.Flags().StringSlice(cobraext.StatusExtraInfoFlagName, nil, fmt.Sprintf(cobraext.StatusExtraInfoFlagDescription, strings.Join(availableExtraInfoParameters, ",")))
cmd.Flags().String(cobraext.StatusFormatFlagName, "table", fmt.Sprintf(cobraext.StatusFormatFlagDescription, strings.Join(availableFormatsParameters, ",")))

return cobraext.NewCommand(cmd, cobraext.ContextPackage)
}
Expand All @@ -86,6 +96,13 @@ func statusCommandAction(cmd *cobra.Command, args []string) error {
if err != nil {
return cobraext.FlagParsingError(err, cobraext.StatusExtraInfoFlagName)
}
format, err := cmd.Flags().GetString(cobraext.StatusFormatFlagName)
if err != nil {
return cobraext.FlagParsingError(err, cobraext.StatusFormatFlagName)
}
if !slices.Contains(availableFormatsParameters, format) {
return cobraext.FlagParsingError(fmt.Errorf("unsupported format %q, supported formats: %s", format, strings.Join(availableFormatsParameters, ",")), cobraext.StatusFormatFlagName)
}

err = validateExtraInfoParameters(extraParameters)
if err != nil {
Expand Down Expand Up @@ -115,7 +132,15 @@ func statusCommandAction(cmd *cobra.Command, args []string) error {
}
}

return print(packageStatus, os.Stdout, extraParameters)
switch format {
case "table":
return print(packageStatus, os.Stdout, extraParameters)
case "json":
return printJSON(packageStatus, os.Stdout, extraParameters)
default:
return errors.New("unknown format")
}

}

func validateExtraInfoParameters(extraParameters []string) error {
Expand Down Expand Up @@ -366,3 +391,86 @@ func releaseFromVersion(version string) string {

return defaultText
}

type statusJSON struct {
Package string `json:"package"`
Owner string `json:"owner,omitempty"`
Versions []statusJSONVersion `json:"versions,omitempty"`
PendingChanges *changelog.Revision `json:"pending_changes,omitempty"`
}

type statusJSONVersion struct {
Environment string `json:"environment,omitempty"`
Version string `json:"version"`
Release string `json:"release,omitempty"`
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`

// Extra parameters
KibanaVersion string `json:"kibana_version,omitempty"`
Subscription string `json:"subscription,omitempty"`
Categories []string `json:"categories,omitempty"`
ServerlessProjectType string `json:"serverless_project_type,omitempty"`
}

func newStatusJSONVersion(environment string, manifest packages.PackageManifest, extraParameters []string) statusJSONVersion {
version := statusJSONVersion{
Environment: environment,
Version: manifest.Version,
Release: strings.ToLower(releaseFromVersion(manifest.Version)),
Title: manifest.Title,
Description: manifest.Description,
}

for _, param := range extraParameters {
switch param {
case kibanaVersionParameter:
version.KibanaVersion = manifest.Conditions.Kibana.Version
case categoriesParameter:
version.Categories = manifest.Categories
case elasticsearchSubscriptionParameter:
version.Subscription = manifest.Conditions.Elastic.Subscription
}
}

return version
}

func printJSON(p *status.PackageStatus, w io.Writer, extraParameters []string) error {
enc := json.NewEncoder(w)
enc.SetEscapeHTML(false)
enc.SetIndent("", " ")

owner := formatOwner(p)
if owner == "-" {
owner = ""
}

info := statusJSON{
Package: p.Name,
Owner: owner,
}

if manifest := p.Local; manifest != nil {
version := newStatusJSONVersion("local", *manifest, extraParameters)
info.Versions = append(info.Versions, version)
info.PendingChanges = p.PendingChanges
}

for _, manifest := range p.Production {
version := newStatusJSONVersion("production", manifest, extraParameters)
info.Versions = append(info.Versions, version)
}

if slices.Contains(extraParameters, serverlessProjectTypesParameter) {
for _, projectType := range p.Serverless {
for _, manifest := range projectType.Manifests {
version := newStatusJSONVersion("production", manifest, extraParameters)
version.ServerlessProjectType = projectType.Name
info.Versions = append(info.Versions, version)
}
}
}

return enc.Encode(info)
}
8 changes: 8 additions & 0 deletions cmd/status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,14 @@ func TestStatusFormatAndPrint(t *testing.T) {

assertOutputWithFile(t, c.expected, buf.String())
})

t.Run(c.title+"/JSON", func(t *testing.T) {
var buf bytes.Buffer
err := printJSON(c.pkgStatus, &buf, c.extraParameters)
require.NoError(t, err)

assertOutputWithFile(t, c.expected+".json", buf.String())
})
}
}

Expand Down
19 changes: 19 additions & 0 deletions cmd/testdata/status-beta-versions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"package": "foo",
"versions": [
{
"environment": "production",
"version": "1.0.0",
"release": "ga",
"title": "Foo",
"description": "Foo integration"
},
{
"environment": "production",
"version": "1.1.0-beta1",
"release": "beta",
"title": "Foo",
"description": "Foo integration"
}
]
}
28 changes: 28 additions & 0 deletions cmd/testdata/status-extra-parameters.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"package": "foo",
"owner": "team",
"versions": [
{
"environment": "local",
"version": "2.0.0-rc1",
"release": "release candidate",
"title": "Foo",
"description": "Foo integration",
"kibana_version": "^8.9.0",
"categories": [
"custom"
]
},
{
"environment": "production",
"version": "1.0.0",
"release": "ga",
"title": "Foo",
"description": "Foo integration",
"kibana_version": "^8.8.0",
"categories": [
"custom"
]
}
]
}
41 changes: 41 additions & 0 deletions cmd/testdata/status-local-version-stage.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"package": "foo",
"owner": "team",
"versions": [
{
"environment": "local",
"version": "2.0.0-rc1",
"release": "release candidate",
"title": "Foo",
"description": "Foo integration"
},
{
"environment": "production",
"version": "1.0.0",
"release": "ga",
"title": "Foo",
"description": "Foo integration"
},
{
"environment": "production",
"version": "1.0.1",
"release": "ga",
"title": "Foo",
"description": "Foo integration"
},
{
"environment": "production",
"version": "1.0.2",
"release": "ga",
"title": "Foo",
"description": "Foo integration"
},
{
"environment": "production",
"version": "1.1.0-beta1",
"release": "beta",
"title": "Foo",
"description": "Foo integration"
}
]
}
3 changes: 3 additions & 0 deletions cmd/testdata/status-no-versions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"package": "foo"
}
30 changes: 30 additions & 0 deletions cmd/testdata/status-pending-changes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"package": "foo",
"owner": "team",
"versions": [
{
"environment": "local",
"version": "2.0.0-rc1",
"release": "release candidate",
"title": "Foo",
"description": "Foo integration"
},
{
"environment": "production",
"version": "1.0.0",
"release": "ga",
"title": "Foo",
"description": "Foo integration"
}
],
"pending_changes": {
"version": "2.0.0-rc2",
"changes": [
{
"description": "New feature",
"type": "enhancement",
"link": "http:github.com/org/repo/pull/2"
}
]
}
}
26 changes: 26 additions & 0 deletions cmd/testdata/status-preview-versions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"package": "foo",
"versions": [
{
"environment": "production",
"version": "0.9.0",
"release": "technical preview",
"title": "Foo",
"description": "Foo integration"
},
{
"environment": "production",
"version": "1.0.0-preview1",
"release": "technical preview",
"title": "Foo",
"description": "Foo integration"
},
{
"environment": "production",
"version": "1.0.0-preview5",
"release": "technical preview",
"title": "Foo",
"description": "Foo integration"
}
]
}
26 changes: 26 additions & 0 deletions cmd/testdata/status-release-candidate-versions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"package": "foo",
"versions": [
{
"environment": "production",
"version": "1.0.0",
"release": "ga",
"title": "Foo",
"description": "Foo integration"
},
{
"environment": "production",
"version": "1.1.0-beta1",
"release": "beta",
"title": "Foo",
"description": "Foo integration"
},
{
"environment": "production",
"version": "2.0.0-rc1",
"release": "release candidate",
"title": "Foo",
"description": "Foo integration"
}
]
}
36 changes: 36 additions & 0 deletions cmd/testdata/status-serverless-projects.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"package": "foo",
"owner": "team",
"versions": [
{
"environment": "local",
"version": "2.0.0-rc1",
"release": "release candidate",
"title": "Foo",
"description": "Foo integration"
},
{
"environment": "production",
"version": "1.0.0",
"release": "ga",
"title": "Foo",
"description": "Foo integration"
},
{
"environment": "production",
"version": "1.0.0",
"release": "ga",
"title": "Foo",
"description": "Foo integration",
"serverless_project_type": "observability"
},
{
"environment": "production",
"version": "1.0.0",
"release": "ga",
"title": "Foo",
"description": "Foo integration",
"serverless_project_type": "security"
}
]
}
Loading

0 comments on commit a75fd6f

Please sign in to comment.