Skip to content

Commit a75fd6f

Browse files
authored
Add JSON format to status subcommand (#1655)
Add a `--format json` option to elastic-package status, that shows the same information but in JSON format.
1 parent a567a70 commit a75fd6f

12 files changed

+341
-1
lines changed

cmd/status.go

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package cmd
66

77
import (
8+
"encoding/json"
89
"errors"
910
"fmt"
1011
"io"
@@ -37,6 +38,9 @@ const (
3738
categoriesParameter = "categories"
3839
elasticsearchSubscriptionParameter = "elastic.subscription"
3940
serverlessProjectTypesParameter = "serverless.project_types"
41+
42+
statusTableFormat = "table"
43+
statusJSONFormat = "json"
4044
)
4145

4246
var (
@@ -50,6 +54,11 @@ var (
5054
elasticsearchSubscriptionParameter,
5155
serverlessProjectTypesParameter,
5256
}
57+
58+
availableFormatsParameters = []string{
59+
statusTableFormat,
60+
statusJSONFormat,
61+
}
5362
)
5463

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

6777
return cobraext.NewCommand(cmd, cobraext.ContextPackage)
6878
}
@@ -86,6 +96,13 @@ func statusCommandAction(cmd *cobra.Command, args []string) error {
8696
if err != nil {
8797
return cobraext.FlagParsingError(err, cobraext.StatusExtraInfoFlagName)
8898
}
99+
format, err := cmd.Flags().GetString(cobraext.StatusFormatFlagName)
100+
if err != nil {
101+
return cobraext.FlagParsingError(err, cobraext.StatusFormatFlagName)
102+
}
103+
if !slices.Contains(availableFormatsParameters, format) {
104+
return cobraext.FlagParsingError(fmt.Errorf("unsupported format %q, supported formats: %s", format, strings.Join(availableFormatsParameters, ",")), cobraext.StatusFormatFlagName)
105+
}
89106

90107
err = validateExtraInfoParameters(extraParameters)
91108
if err != nil {
@@ -115,7 +132,15 @@ func statusCommandAction(cmd *cobra.Command, args []string) error {
115132
}
116133
}
117134

118-
return print(packageStatus, os.Stdout, extraParameters)
135+
switch format {
136+
case "table":
137+
return print(packageStatus, os.Stdout, extraParameters)
138+
case "json":
139+
return printJSON(packageStatus, os.Stdout, extraParameters)
140+
default:
141+
return errors.New("unknown format")
142+
}
143+
119144
}
120145

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

367392
return defaultText
368393
}
394+
395+
type statusJSON struct {
396+
Package string `json:"package"`
397+
Owner string `json:"owner,omitempty"`
398+
Versions []statusJSONVersion `json:"versions,omitempty"`
399+
PendingChanges *changelog.Revision `json:"pending_changes,omitempty"`
400+
}
401+
402+
type statusJSONVersion struct {
403+
Environment string `json:"environment,omitempty"`
404+
Version string `json:"version"`
405+
Release string `json:"release,omitempty"`
406+
Title string `json:"title,omitempty"`
407+
Description string `json:"description,omitempty"`
408+
409+
// Extra parameters
410+
KibanaVersion string `json:"kibana_version,omitempty"`
411+
Subscription string `json:"subscription,omitempty"`
412+
Categories []string `json:"categories,omitempty"`
413+
ServerlessProjectType string `json:"serverless_project_type,omitempty"`
414+
}
415+
416+
func newStatusJSONVersion(environment string, manifest packages.PackageManifest, extraParameters []string) statusJSONVersion {
417+
version := statusJSONVersion{
418+
Environment: environment,
419+
Version: manifest.Version,
420+
Release: strings.ToLower(releaseFromVersion(manifest.Version)),
421+
Title: manifest.Title,
422+
Description: manifest.Description,
423+
}
424+
425+
for _, param := range extraParameters {
426+
switch param {
427+
case kibanaVersionParameter:
428+
version.KibanaVersion = manifest.Conditions.Kibana.Version
429+
case categoriesParameter:
430+
version.Categories = manifest.Categories
431+
case elasticsearchSubscriptionParameter:
432+
version.Subscription = manifest.Conditions.Elastic.Subscription
433+
}
434+
}
435+
436+
return version
437+
}
438+
439+
func printJSON(p *status.PackageStatus, w io.Writer, extraParameters []string) error {
440+
enc := json.NewEncoder(w)
441+
enc.SetEscapeHTML(false)
442+
enc.SetIndent("", " ")
443+
444+
owner := formatOwner(p)
445+
if owner == "-" {
446+
owner = ""
447+
}
448+
449+
info := statusJSON{
450+
Package: p.Name,
451+
Owner: owner,
452+
}
453+
454+
if manifest := p.Local; manifest != nil {
455+
version := newStatusJSONVersion("local", *manifest, extraParameters)
456+
info.Versions = append(info.Versions, version)
457+
info.PendingChanges = p.PendingChanges
458+
}
459+
460+
for _, manifest := range p.Production {
461+
version := newStatusJSONVersion("production", manifest, extraParameters)
462+
info.Versions = append(info.Versions, version)
463+
}
464+
465+
if slices.Contains(extraParameters, serverlessProjectTypesParameter) {
466+
for _, projectType := range p.Serverless {
467+
for _, manifest := range projectType.Manifests {
468+
version := newStatusJSONVersion("production", manifest, extraParameters)
469+
version.ServerlessProjectType = projectType.Name
470+
info.Versions = append(info.Versions, version)
471+
}
472+
}
473+
}
474+
475+
return enc.Encode(info)
476+
}

cmd/status_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,14 @@ func TestStatusFormatAndPrint(t *testing.T) {
187187

188188
assertOutputWithFile(t, c.expected, buf.String())
189189
})
190+
191+
t.Run(c.title+"/JSON", func(t *testing.T) {
192+
var buf bytes.Buffer
193+
err := printJSON(c.pkgStatus, &buf, c.extraParameters)
194+
require.NoError(t, err)
195+
196+
assertOutputWithFile(t, c.expected+".json", buf.String())
197+
})
190198
}
191199
}
192200

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"package": "foo",
3+
"versions": [
4+
{
5+
"environment": "production",
6+
"version": "1.0.0",
7+
"release": "ga",
8+
"title": "Foo",
9+
"description": "Foo integration"
10+
},
11+
{
12+
"environment": "production",
13+
"version": "1.1.0-beta1",
14+
"release": "beta",
15+
"title": "Foo",
16+
"description": "Foo integration"
17+
}
18+
]
19+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"package": "foo",
3+
"owner": "team",
4+
"versions": [
5+
{
6+
"environment": "local",
7+
"version": "2.0.0-rc1",
8+
"release": "release candidate",
9+
"title": "Foo",
10+
"description": "Foo integration",
11+
"kibana_version": "^8.9.0",
12+
"categories": [
13+
"custom"
14+
]
15+
},
16+
{
17+
"environment": "production",
18+
"version": "1.0.0",
19+
"release": "ga",
20+
"title": "Foo",
21+
"description": "Foo integration",
22+
"kibana_version": "^8.8.0",
23+
"categories": [
24+
"custom"
25+
]
26+
}
27+
]
28+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"package": "foo",
3+
"owner": "team",
4+
"versions": [
5+
{
6+
"environment": "local",
7+
"version": "2.0.0-rc1",
8+
"release": "release candidate",
9+
"title": "Foo",
10+
"description": "Foo integration"
11+
},
12+
{
13+
"environment": "production",
14+
"version": "1.0.0",
15+
"release": "ga",
16+
"title": "Foo",
17+
"description": "Foo integration"
18+
},
19+
{
20+
"environment": "production",
21+
"version": "1.0.1",
22+
"release": "ga",
23+
"title": "Foo",
24+
"description": "Foo integration"
25+
},
26+
{
27+
"environment": "production",
28+
"version": "1.0.2",
29+
"release": "ga",
30+
"title": "Foo",
31+
"description": "Foo integration"
32+
},
33+
{
34+
"environment": "production",
35+
"version": "1.1.0-beta1",
36+
"release": "beta",
37+
"title": "Foo",
38+
"description": "Foo integration"
39+
}
40+
]
41+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"package": "foo"
3+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"package": "foo",
3+
"owner": "team",
4+
"versions": [
5+
{
6+
"environment": "local",
7+
"version": "2.0.0-rc1",
8+
"release": "release candidate",
9+
"title": "Foo",
10+
"description": "Foo integration"
11+
},
12+
{
13+
"environment": "production",
14+
"version": "1.0.0",
15+
"release": "ga",
16+
"title": "Foo",
17+
"description": "Foo integration"
18+
}
19+
],
20+
"pending_changes": {
21+
"version": "2.0.0-rc2",
22+
"changes": [
23+
{
24+
"description": "New feature",
25+
"type": "enhancement",
26+
"link": "http:github.com/org/repo/pull/2"
27+
}
28+
]
29+
}
30+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"package": "foo",
3+
"versions": [
4+
{
5+
"environment": "production",
6+
"version": "0.9.0",
7+
"release": "technical preview",
8+
"title": "Foo",
9+
"description": "Foo integration"
10+
},
11+
{
12+
"environment": "production",
13+
"version": "1.0.0-preview1",
14+
"release": "technical preview",
15+
"title": "Foo",
16+
"description": "Foo integration"
17+
},
18+
{
19+
"environment": "production",
20+
"version": "1.0.0-preview5",
21+
"release": "technical preview",
22+
"title": "Foo",
23+
"description": "Foo integration"
24+
}
25+
]
26+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"package": "foo",
3+
"versions": [
4+
{
5+
"environment": "production",
6+
"version": "1.0.0",
7+
"release": "ga",
8+
"title": "Foo",
9+
"description": "Foo integration"
10+
},
11+
{
12+
"environment": "production",
13+
"version": "1.1.0-beta1",
14+
"release": "beta",
15+
"title": "Foo",
16+
"description": "Foo integration"
17+
},
18+
{
19+
"environment": "production",
20+
"version": "2.0.0-rc1",
21+
"release": "release candidate",
22+
"title": "Foo",
23+
"description": "Foo integration"
24+
}
25+
]
26+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"package": "foo",
3+
"owner": "team",
4+
"versions": [
5+
{
6+
"environment": "local",
7+
"version": "2.0.0-rc1",
8+
"release": "release candidate",
9+
"title": "Foo",
10+
"description": "Foo integration"
11+
},
12+
{
13+
"environment": "production",
14+
"version": "1.0.0",
15+
"release": "ga",
16+
"title": "Foo",
17+
"description": "Foo integration"
18+
},
19+
{
20+
"environment": "production",
21+
"version": "1.0.0",
22+
"release": "ga",
23+
"title": "Foo",
24+
"description": "Foo integration",
25+
"serverless_project_type": "observability"
26+
},
27+
{
28+
"environment": "production",
29+
"version": "1.0.0",
30+
"release": "ga",
31+
"title": "Foo",
32+
"description": "Foo integration",
33+
"serverless_project_type": "security"
34+
}
35+
]
36+
}

0 commit comments

Comments
 (0)