Skip to content

Commit c6bac50

Browse files
authored
Allow to specify the output format of func version via --output (#3280)
* Allow to specify the output format of `func version` via `--output` Allows to print the output from `func version` as `json` or `yaml` too * Move version struct to version.go * Run `hack/update-codegen.sh` * Fix unit test to expect the correct number of lines
1 parent e30bcf9 commit c6bac50

4 files changed

Lines changed: 144 additions & 66 deletions

File tree

cmd/root.go

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"path/filepath"
88
"strings"
99

10-
"github.com/Masterminds/semver"
1110
"github.com/ory/viper"
1211
"github.com/spf13/cobra"
1312
"github.com/spf13/pflag"
@@ -340,60 +339,6 @@ func cwd() (cwd string) {
340339
return cwd
341340
}
342341

343-
// Version information populated on build.
344-
type Version struct {
345-
// Version tag of the git commit, or 'tip' if no tag.
346-
Vers string
347-
// Kver is the version of knative in which func was most recently
348-
// If the build is not tagged as being released with a specific Knative
349-
// build, this is the most recent version of knative along with a suffix
350-
// consisting of the number of commits which have been added since it was
351-
// included in Knative.
352-
Kver string
353-
// Hash of the currently active git commit on build.
354-
Hash string
355-
// Verbose printing enabled for the string representation.
356-
Verbose bool
357-
}
358-
359-
// Return the stringification of the Version struct.
360-
func (v Version) String() string {
361-
// Initialize the default value to the zero semver with a descriptive
362-
// metadta tag indicating this must have been built from source if
363-
// undefined:
364-
if v.Vers == "" {
365-
v.Vers = DefaultVersion
366-
}
367-
if v.Verbose {
368-
return v.StringVerbose()
369-
}
370-
_ = semver.MustParse(v.Vers)
371-
return v.Vers
372-
}
373-
374-
// StringVerbose returns the version along with extended version metadata.
375-
func (v Version) StringVerbose() string {
376-
var (
377-
vers = v.Vers
378-
kver = v.Kver
379-
hash = v.Hash
380-
)
381-
if strings.HasPrefix(kver, "knative-") {
382-
kver = strings.Split(kver, "-")[1]
383-
}
384-
return fmt.Sprintf(
385-
"Version: %s\n"+
386-
"Knative: %s\n"+
387-
"Commit: %s\n"+
388-
"SocatImage: %s\n"+
389-
"TarImage: %s\n",
390-
vers,
391-
kver,
392-
hash,
393-
k8s.SocatImage,
394-
k8s.TarImage)
395-
}
396-
397342
// surveySelectDefault returns 'value' if defined and exists in 'options'.
398343
// Otherwise, options[0] is returned if it exists. Empty string otherwise.
399344
//

cmd/root_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ func TestVerbose(t *testing.T) {
171171
name: "verbose as version's flag",
172172
args: []string{"version", "-v"},
173173
want: "Version: v0.42.0",
174-
wantLF: 6,
174+
wantLF: 5,
175175
},
176176
{
177177
name: "no verbose",

cmd/version.go

Lines changed: 131 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
package cmd
22

33
import (
4+
"encoding/json"
45
"fmt"
6+
"io"
7+
"strings"
58

9+
"github.com/Masterminds/semver"
610
"github.com/ory/viper"
711
"github.com/spf13/cobra"
12+
"gopkg.in/yaml.v2"
13+
814
"knative.dev/func/pkg/config"
15+
"knative.dev/func/pkg/k8s"
916
)
1017

1118
func NewVersionCmd(version Version) *cobra.Command {
@@ -17,11 +24,12 @@ NAME
1724
{{rootCmdUse}} version - function version information.
1825
1926
SYNOPSIS
20-
{{rootCmdUse}} version [-v|--verbose]
27+
{{rootCmdUse}} version [-v|--verbose] [-o|--output]
2128
2229
DESCRIPTION
2330
Print version information. Use the --verbose option to see date stamp and
24-
associated git source control hash if available.
31+
associated git source control hash if available. Use the --output option
32+
to specify the output format (human|json|yaml).
2533
2634
o Print the functions version
2735
$ {{rootCmdUse}} version
@@ -30,9 +38,15 @@ DESCRIPTION
3038
metadata.
3139
$ {{rootCmdUse}} version -v
3240
41+
o Print the version information in JSON format
42+
$ {{rootCmdUse}} version --output json
43+
44+
o Print verbose version information in YAML format
45+
$ {{rootCmdUse}} version -v -o yaml
46+
3347
`,
3448
SuggestFor: []string{"vers", "version"}, //nolint:misspell
35-
PreRunE: bindEnv("verbose"),
49+
PreRunE: bindEnv("verbose", "output"),
3650
Run: func(cmd *cobra.Command, _ []string) {
3751
runVersion(cmd, version)
3852
},
@@ -41,13 +55,124 @@ DESCRIPTION
4155
if err != nil {
4256
fmt.Fprintf(cmd.OutOrStdout(), "error loading config at '%v'. %v\n", config.File(), err)
4357
}
58+
59+
// Add flags
60+
cmd.Flags().StringP("output", "o", "human", "Output format (human|json|yaml) ($FUNC_OUTPUT)")
4461
addVerboseFlag(cmd, cfg.Verbose)
4562

63+
// Add flag completion
64+
if err := cmd.RegisterFlagCompletionFunc("output", CompleteOutputFormatList); err != nil {
65+
fmt.Println("internal: error while calling RegisterFlagCompletionFunc: ", err)
66+
}
67+
4668
return cmd
4769
}
4870

4971
// Run
50-
func runVersion(cmd *cobra.Command, version Version) {
51-
version.Verbose = viper.GetBool("verbose")
52-
fmt.Fprintf(cmd.OutOrStdout(), "%v\n", version)
72+
func runVersion(cmd *cobra.Command, v Version) {
73+
verbose := viper.GetBool("verbose")
74+
output := viper.GetString("output")
75+
76+
// Set verbose flag
77+
v.Verbose = verbose
78+
79+
// Initialize the default value to the zero semver with a descriptive
80+
// metadta tag indicating this must have been built from source if
81+
// undefined:
82+
if v.Vers == "" {
83+
v.Vers = DefaultVersion
84+
}
85+
86+
// Kver, Hash are already set from build
87+
// Populate image fields from k8s package constants
88+
v.SocatImage = k8s.SocatImage
89+
v.TarImage = k8s.TarImage
90+
91+
write(cmd.OutOrStdout(), v, output)
92+
}
93+
94+
// Version information populated on build.
95+
type Version struct {
96+
// Version tag of the git commit, or 'tip' if no tag.
97+
Vers string `json:"version,omitempty" yaml:"version,omitempty"`
98+
// Kver is the version of knative in which func was most recently
99+
// If the build is not tagged as being released with a specific Knative
100+
// build, this is the most recent version of knative along with a suffix
101+
// consisting of the number of commits which have been added since it was
102+
// included in Knative.
103+
Kver string `json:"knative,omitempty" yaml:"knative,omitempty"`
104+
// Hash of the currently active git commit on build.
105+
Hash string `json:"commit,omitempty" yaml:"commit,omitempty"`
106+
// SocatImage is the socat image used by the function.
107+
SocatImage string `json:"socatImage,omitempty" yaml:"socatImage,omitempty"`
108+
// TarImage is the tar image used by the function.
109+
TarImage string `json:"tarImage,omitempty" yaml:"tarImage,omitempty"`
110+
// Verbose printing enabled for the string representation.
111+
Verbose bool `json:"-" yaml:"-"`
112+
}
113+
114+
// Return the stringification of the Version struct.
115+
func (v Version) String() string {
116+
if v.Verbose {
117+
return v.StringVerbose()
118+
}
119+
_ = semver.MustParse(v.Vers)
120+
return v.Vers
121+
}
122+
123+
// StringVerbose returns the version along with extended version metadata.
124+
func (v Version) StringVerbose() string {
125+
var (
126+
vers = v.Vers
127+
kver = v.Kver
128+
hash = v.Hash
129+
)
130+
if strings.HasPrefix(kver, "knative-") {
131+
kver = strings.Split(kver, "-")[1]
132+
}
133+
return fmt.Sprintf(
134+
"Version: %s\n"+
135+
"Knative: %s\n"+
136+
"Commit: %s\n"+
137+
"SocatImage: %s\n"+
138+
"TarImage: %s\n",
139+
vers,
140+
kver,
141+
hash,
142+
v.SocatImage,
143+
v.TarImage)
144+
}
145+
146+
// Human prints version information in human-readable format.
147+
func (v Version) Human(w io.Writer) error {
148+
if v.Verbose {
149+
_, err := fmt.Fprint(w, v.StringVerbose())
150+
return err
151+
}
152+
_, err := fmt.Fprintf(w, "%s\n", v.Vers)
153+
return err
154+
}
155+
156+
// Plain prints version information in plain format (same as human for version).
157+
func (v Version) Plain(w io.Writer) error {
158+
return v.Human(w)
159+
}
160+
161+
// JSON prints version information in JSON format.
162+
func (v Version) JSON(w io.Writer) error {
163+
enc := json.NewEncoder(w)
164+
enc.SetIndent("", " ")
165+
return enc.Encode(v)
166+
}
167+
168+
// YAML prints version information in YAML format.
169+
func (v Version) YAML(w io.Writer) error {
170+
enc := yaml.NewEncoder(w)
171+
defer enc.Close()
172+
return enc.Encode(v)
173+
}
174+
175+
// URL is not supported for version command.
176+
func (v Version) URL(w io.Writer) error {
177+
return fmt.Errorf("URL format not supported for version command")
53178
}

docs/reference/func_version.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ NAME
99
func version - function version information.
1010

1111
SYNOPSIS
12-
func version [-v|--verbose]
12+
func version [-v|--verbose] [-o|--output]
1313

1414
DESCRIPTION
1515
Print version information. Use the --verbose option to see date stamp and
16-
associated git source control hash if available.
16+
associated git source control hash if available. Use the --output option
17+
to specify the output format (human|json|yaml).
1718

1819
o Print the functions version
1920
$ func version
@@ -22,6 +23,12 @@ DESCRIPTION
2223
metadata.
2324
$ func version -v
2425

26+
o Print the version information in JSON format
27+
$ func version --output json
28+
29+
o Print verbose version information in YAML format
30+
$ func version -v -o yaml
31+
2532

2633

2734
```
@@ -31,8 +38,9 @@ func version
3138
### Options
3239

3340
```
34-
-h, --help help for version
35-
-v, --verbose Print verbose logs ($FUNC_VERBOSE)
41+
-h, --help help for version
42+
-o, --output string Output format (human|json|yaml) ($FUNC_OUTPUT) (default "human")
43+
-v, --verbose Print verbose logs ($FUNC_VERBOSE)
3644
```
3745

3846
### SEE ALSO

0 commit comments

Comments
 (0)