Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Mar 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
|===
| | 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)
| https://github.com/knative/client/issues/564[#564]
Expand Down
3 changes: 2 additions & 1 deletion docs/cmd/kn_version.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ kn version [flags]
### Options

```
-h, --help help for version
-h, --help help for version
-o, --output string Output format. One of: json|yaml.
```

### Options inherited from parent commands
Expand Down
48 changes: 45 additions & 3 deletions pkg/kn/commands/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
package version

import (
"encoding/json"
"fmt"

"knative.dev/client/pkg/kn/commands"

"github.com/spf13/cobra"
"sigs.k8s.io/yaml"

"knative.dev/client/pkg/kn/commands"
)

var Version string
Expand All @@ -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
func NewVersionCommand(p *commands.KnParams) *cobra.Command {
versionCmd := &cobra.Command{
Use: "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()
fmt.Fprintf(out, "Version: %s\n", Version)
fmt.Fprintf(out, "Build Date: %s\n", BuildDate)
Expand All @@ -57,7 +69,37 @@ func NewVersionCommand(p *commands.KnParams) *cobra.Command {
for _, api := range apiVersions["eventing"] {
fmt.Fprintf(out, " - %s\n", api)
}
return nil
},
}
versionCmd.Flags().StringP(
"output",
"o",
"",
"Output format. One of: json|yaml.",
)
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'.")
navidshaikh marked this conversation as resolved.
Show resolved Hide resolved
}
return nil
}
88 changes: 54 additions & 34 deletions pkg/kn/commands/version/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,25 @@ package version

import (
"bytes"
"encoding/json"
"testing"
"text/template"

"knative.dev/client/pkg/kn/commands"

"github.com/spf13/cobra"
"gotest.tools/assert"
)
"sigs.k8s.io/yaml"

type versionOutput struct {
Version string
BuildDate string
GitRevision string
}
"knative.dev/client/pkg/kn/commands"
)

var versionOutputTemplate = `Version: {{.Version}}
Build Date: {{.BuildDate}}
Git Revision: {{.GitRevision}}
Supported APIs:
* Serving
- serving.knative.dev/v1 (knative-serving v0.13.0)
* Eventing
- sources.eventing.knative.dev/v1alpha1 (knative-eventing v0.13.1)
- sources.eventing.knative.dev/v1alpha2 (knative-eventing v0.13.1)
- eventing.knative.dev/v1alpha1 (knative-eventing v0.13.1)
* Serving{{range $apis := .SupportedAPIs.serving }}
- {{$apis}}{{end}}
* Eventing{{range $apis := .SupportedAPIs.eventing }}
- {{$apis}}{{end}}
`

const (
Expand All @@ -51,53 +45,79 @@ const (

func TestVersion(t *testing.T) {
var (
versionCmd *cobra.Command
knParams *commands.KnParams
expectedVersionOutput string
output *bytes.Buffer
versionCmd *cobra.Command
knParams *commands.KnParams
expectedOutput string
knVersionObj knVersion
output *bytes.Buffer
)

setup := func() {
Version = fakeVersion
BuildDate = fakeBuildDate
GitRevision = fakeGitRevision

expectedVersionOutput = genVersionOuput(t, versionOutputTemplate,
versionOutput{
fakeVersion,
fakeBuildDate,
fakeGitRevision})

knVersionObj = knVersion{fakeVersion, fakeBuildDate, fakeGitRevision, apiVersions}
expectedOutput = genVersionOuput(t, knVersionObj)
knParams = &commands.KnParams{}
versionCmd = NewVersionCommand(knParams)
output = new(bytes.Buffer)
versionCmd.SetOutput(output)
}

t.Run("creates a VersionCommand", func(t *testing.T) {
runVersionCmd := func(args []string) error {
setup()
versionCmd.SetArgs(args)
return versionCmd.Execute()
}

t.Run("creates a VersionCommand", func(t *testing.T) {
setup()
assert.Equal(t, versionCmd.Use, "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) {
setup()
err := runVersionCmd([]string{})
assert.NilError(t, err)
assert.Equal(t, output.String(), expectedOutput)
})

versionCmd.Run(versionCmd, []string{})
assert.Equal(t, output.String(), expectedVersionOutput)
t.Run("print version command with machine readable output", func(t *testing.T) {
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)
assert.NilError(t, err)

buf := bytes.Buffer{}
err = tmpl.Execute(&buf, vOutput)
err = tmpl.Execute(&buf, obj)
assert.NilError(t, err)

return buf.String()
}