feat(version): Add JSON/YAML output formats for version command (#709)

* feat(version): Add JSON/YAML output format for version command

 Fixes #513

* Loop for supported apis in template
This commit is contained in:
Navid Shaikh 2020-03-09 23:41:29 +05:30 committed by GitHub
parent 158c8f8980
commit 14a5e83765
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 105 additions and 38 deletions

View File

@ -18,6 +18,10 @@
|=== |===
| | Description | PR | | Description | PR
| 🎁
| Add JSON/YAML output format for version command
| https://github.com/knative/client/pull/709[#709]
| 🐣 | 🐣
| Replaced `kn source cron` with `kn source ping`. `--schedule` is not mandatory anymore and defaults to "* * * * *" (every minute) | Replaced `kn source cron` with `kn source ping`. `--schedule` is not mandatory anymore and defaults to "* * * * *" (every minute)
| https://github.com/knative/client/issues/564[#564] | https://github.com/knative/client/issues/564[#564]

View File

@ -14,6 +14,7 @@ kn version [flags]
``` ```
-h, --help help for version -h, --help help for version
-o, --output string Output format. One of: json|yaml.
``` ```
### Options inherited from parent commands ### Options inherited from parent commands

View File

@ -15,11 +15,13 @@
package version package version
import ( import (
"encoding/json"
"fmt" "fmt"
"knative.dev/client/pkg/kn/commands"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"sigs.k8s.io/yaml"
"knative.dev/client/pkg/kn/commands"
) )
var Version string var Version string
@ -38,12 +40,22 @@ var apiVersions = map[string][]string{
}, },
} }
type knVersion struct {
Version string
BuildDate string
GitRevision string
SupportedAPIs map[string][]string
}
// NewVersionCommand implements 'kn version' command // NewVersionCommand implements 'kn version' command
func NewVersionCommand(p *commands.KnParams) *cobra.Command { func NewVersionCommand(p *commands.KnParams) *cobra.Command {
versionCmd := &cobra.Command{ versionCmd := &cobra.Command{
Use: "version", Use: "version",
Short: "Prints the client version", Short: "Prints the client version",
Run: func(cmd *cobra.Command, args []string) { RunE: func(cmd *cobra.Command, args []string) error {
if cmd.Flags().Changed("output") {
return printVersionMachineReadable(cmd)
}
out := cmd.OutOrStdout() out := cmd.OutOrStdout()
fmt.Fprintf(out, "Version: %s\n", Version) fmt.Fprintf(out, "Version: %s\n", Version)
fmt.Fprintf(out, "Build Date: %s\n", BuildDate) fmt.Fprintf(out, "Build Date: %s\n", BuildDate)
@ -57,7 +69,37 @@ func NewVersionCommand(p *commands.KnParams) *cobra.Command {
for _, api := range apiVersions["eventing"] { for _, api := range apiVersions["eventing"] {
fmt.Fprintf(out, " - %s\n", api) fmt.Fprintf(out, " - %s\n", api)
} }
return nil
}, },
} }
versionCmd.Flags().StringP(
"output",
"o",
"",
"Output format. One of: json|yaml.",
)
return versionCmd return versionCmd
} }
func printVersionMachineReadable(cmd *cobra.Command) error {
out := cmd.OutOrStdout()
v := knVersion{Version, BuildDate, GitRevision, apiVersions}
format := cmd.Flag("output").Value.String()
switch format {
case "JSON", "json":
b, err := json.MarshalIndent(v, "", "\t")
if err != nil {
return err
}
fmt.Fprint(out, string(b))
case "YAML", "yaml":
b, err := yaml.Marshal(v)
if err != nil {
return err
}
fmt.Fprint(out, string(b))
default:
return fmt.Errorf("Invalid value for output flag, choose one among 'json' or 'yaml'.")
}
return nil
}

View File

@ -16,31 +16,25 @@ package version
import ( import (
"bytes" "bytes"
"encoding/json"
"testing" "testing"
"text/template" "text/template"
"knative.dev/client/pkg/kn/commands"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"gotest.tools/assert" "gotest.tools/assert"
) "sigs.k8s.io/yaml"
type versionOutput struct { "knative.dev/client/pkg/kn/commands"
Version string )
BuildDate string
GitRevision string
}
var versionOutputTemplate = `Version: {{.Version}} var versionOutputTemplate = `Version: {{.Version}}
Build Date: {{.BuildDate}} Build Date: {{.BuildDate}}
Git Revision: {{.GitRevision}} Git Revision: {{.GitRevision}}
Supported APIs: Supported APIs:
* Serving * Serving{{range $apis := .SupportedAPIs.serving }}
- serving.knative.dev/v1 (knative-serving v0.13.0) - {{$apis}}{{end}}
* Eventing * Eventing{{range $apis := .SupportedAPIs.eventing }}
- sources.eventing.knative.dev/v1alpha1 (knative-eventing v0.13.1) - {{$apis}}{{end}}
- sources.eventing.knative.dev/v1alpha2 (knative-eventing v0.13.1)
- eventing.knative.dev/v1alpha1 (knative-eventing v0.13.1)
` `
const ( const (
@ -53,7 +47,8 @@ func TestVersion(t *testing.T) {
var ( var (
versionCmd *cobra.Command versionCmd *cobra.Command
knParams *commands.KnParams knParams *commands.KnParams
expectedVersionOutput string expectedOutput string
knVersionObj knVersion
output *bytes.Buffer output *bytes.Buffer
) )
@ -61,43 +56,68 @@ func TestVersion(t *testing.T) {
Version = fakeVersion Version = fakeVersion
BuildDate = fakeBuildDate BuildDate = fakeBuildDate
GitRevision = fakeGitRevision GitRevision = fakeGitRevision
knVersionObj = knVersion{fakeVersion, fakeBuildDate, fakeGitRevision, apiVersions}
expectedVersionOutput = genVersionOuput(t, versionOutputTemplate, expectedOutput = genVersionOuput(t, knVersionObj)
versionOutput{
fakeVersion,
fakeBuildDate,
fakeGitRevision})
knParams = &commands.KnParams{} knParams = &commands.KnParams{}
versionCmd = NewVersionCommand(knParams) versionCmd = NewVersionCommand(knParams)
output = new(bytes.Buffer) output = new(bytes.Buffer)
versionCmd.SetOutput(output) versionCmd.SetOutput(output)
} }
runVersionCmd := func(args []string) error {
setup()
versionCmd.SetArgs(args)
return versionCmd.Execute()
}
t.Run("creates a VersionCommand", func(t *testing.T) { t.Run("creates a VersionCommand", func(t *testing.T) {
setup() setup()
assert.Equal(t, versionCmd.Use, "version") assert.Equal(t, versionCmd.Use, "version")
assert.Equal(t, versionCmd.Short, "Prints the client version") assert.Equal(t, versionCmd.Short, "Prints the client version")
assert.Assert(t, versionCmd.Run != nil) assert.Assert(t, versionCmd.RunE != nil)
}) })
t.Run("prints version, build date, git revision, supported APIs", func(t *testing.T) { t.Run("prints version, build date, git revision, supported APIs", func(t *testing.T) {
setup() err := runVersionCmd([]string{})
assert.NilError(t, err)
assert.Equal(t, output.String(), expectedOutput)
})
versionCmd.Run(versionCmd, []string{}) t.Run("print version command with machine readable output", func(t *testing.T) {
assert.Equal(t, output.String(), expectedVersionOutput) t.Run("json", func(t *testing.T) {
err := runVersionCmd([]string{"-oJSON"})
assert.NilError(t, err)
in := knVersion{}
err = json.Unmarshal(output.Bytes(), &in)
assert.NilError(t, err)
assert.DeepEqual(t, in, knVersionObj)
})
t.Run("yaml", func(t *testing.T) {
err := runVersionCmd([]string{"-oyaml"})
assert.NilError(t, err)
jsonData, err := yaml.YAMLToJSON(output.Bytes())
assert.NilError(t, err)
in := knVersion{}
err = json.Unmarshal(jsonData, &in)
assert.NilError(t, err)
assert.DeepEqual(t, in, knVersionObj)
})
t.Run("invalid format", func(t *testing.T) {
err := runVersionCmd([]string{"-o", "jsonpath"})
assert.Assert(t, err != nil)
assert.ErrorContains(t, err, "Invalid", "output", "flag", "choose", "among")
})
}) })
} }
func genVersionOuput(t *testing.T, templ string, vOutput versionOutput) string { func genVersionOuput(t *testing.T, obj knVersion) string {
tmpl, err := template.New("versionOutput").Parse(versionOutputTemplate) tmpl, err := template.New("versionOutput").Parse(versionOutputTemplate)
assert.NilError(t, err) assert.NilError(t, err)
buf := bytes.Buffer{} buf := bytes.Buffer{}
err = tmpl.Execute(&buf, vOutput) err = tmpl.Execute(&buf, obj)
assert.NilError(t, err) assert.NilError(t, err)
return buf.String() return buf.String()
} }