Skip to content

Commit 7f7cdda

Browse files
authored
feat: Print version with Client and Server (#108)
Issue #, if available: #12 *Description of changes:* Update the implementation `finch version` according to #12 (comment) #### License Acceptance By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. Signed-off-by: Ahsan Khan <[email protected]> Signed-off-by: Ahsan Khan <[email protected]>
1 parent 8d06eec commit 7f7cdda

File tree

9 files changed

+305
-49
lines changed

9 files changed

+305
-49
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ CORE_OUTDIR := $(CURDIR)/$(CORE_FILENAME)/_output
2727
CORE_VDE_PREFIX ?= $(OUTDIR)/dependencies/vde/opt/finch
2828
LICENSEDIR := $(OUTDIR)/license-files
2929
VERSION := $(shell git describe --match 'v[0-9]*' --dirty='.modified' --always --tags)
30-
LDFLAGS := "-X $(PACKAGE)/pkg/version.Version=$(VERSION)"
30+
GITCOMMIT := $(shell git rev-parse HEAD)$(shell if ! git diff --no-ext-diff --quiet --exit-code; then echo .m; fi)
31+
LDFLAGS := "-X $(PACKAGE)/pkg/version.Version=$(VERSION) -X $(PACKAGE)/pkg/version.GitCommit=$(GITCOMMIT)"
3132

3233
.DEFAULT_GOAL := all
3334

cmd/finch/main.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ package main
66

77
import (
88
"fmt"
9+
"io"
10+
"os"
911

1012
"github.com/runfinch/finch/pkg/disk"
1113

@@ -18,6 +20,7 @@ import (
1820
"github.com/runfinch/finch/pkg/fssh"
1921
"github.com/runfinch/finch/pkg/path"
2022
"github.com/runfinch/finch/pkg/system"
23+
"github.com/runfinch/finch/pkg/version"
2124

2225
"github.com/spf13/afero"
2326
"github.com/spf13/cobra"
@@ -30,12 +33,19 @@ func main() {
3033
stdLib := system.NewStdLib()
3134
fs := afero.NewOsFs()
3235
mem := fmemory.NewMemory()
33-
if err := xmain(logger, stdLib, fs, stdLib, mem); err != nil {
36+
stdOut := os.Stdout
37+
if err := xmain(logger, stdLib, fs, stdLib, mem, stdOut); err != nil {
3438
logger.Fatal(err)
3539
}
3640
}
3741

38-
func xmain(logger flog.Logger, ffd path.FinchFinderDeps, fs afero.Fs, loadCfgDeps config.LoadSystemDeps, mem fmemory.Memory) error {
42+
func xmain(logger flog.Logger,
43+
ffd path.FinchFinderDeps,
44+
fs afero.Fs,
45+
loadCfgDeps config.LoadSystemDeps,
46+
mem fmemory.Memory,
47+
stdOut io.Writer,
48+
) error {
3949
fp, err := path.FindFinch(ffd)
4050
if err != nil {
4151
return fmt.Errorf("failed to find the installation path of Finch: %w", err)
@@ -46,17 +56,17 @@ func xmain(logger flog.Logger, ffd path.FinchFinderDeps, fs afero.Fs, loadCfgDep
4656
return fmt.Errorf("failed to load config: %w", err)
4757
}
4858

49-
return newApp(logger, fp, fs, fc).Execute()
59+
return newApp(logger, fp, fs, fc, stdOut).Execute()
5060
}
5161

52-
var newApp = func(logger flog.Logger, fp path.Finch, fs afero.Fs, fc *config.Finch) *cobra.Command {
62+
var newApp = func(logger flog.Logger, fp path.Finch, fs afero.Fs, fc *config.Finch, stdOut io.Writer) *cobra.Command {
5363
usage := fmt.Sprintf("%v <command>", finchRootCmd)
5464
rootCmd := &cobra.Command{
5565
Use: usage,
5666
Short: "Finch: open-source container development tool",
5767
SilenceUsage: true,
5868
SilenceErrors: true,
59-
Version: finchVersion,
69+
Version: version.Version,
6070
}
6171
// TODO: Decide when to forward --debug to the dependencies
6272
// (e.g. nerdctl for container commands and limactl for VM commands).
@@ -83,7 +93,7 @@ var newApp = func(logger flog.Logger, fp path.Finch, fs afero.Fs, fc *config.Fin
8393
allCommands := initializeNerdctlCommands(lcc, logger)
8494
// append finch specific commands
8595
allCommands = append(allCommands,
86-
newVersionCommand(),
96+
newVersionCommand(lcc, logger, stdOut),
8797
virtualMachineCommands(logger, fp, lcc, ecc, fs, fc),
8898
)
8999

cmd/finch/main_test.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package main
66
import (
77
"errors"
88
"fmt"
9+
"os"
910
"testing"
1011

1112
"gopkg.in/yaml.v3"
@@ -14,6 +15,7 @@ import (
1415
"github.com/runfinch/finch/pkg/flog"
1516
"github.com/runfinch/finch/pkg/mocks"
1617
"github.com/runfinch/finch/pkg/path"
18+
"github.com/runfinch/finch/pkg/version"
1719

1820
"github.com/golang/mock/gomock"
1921
"github.com/spf13/afero"
@@ -111,8 +113,9 @@ func TestXmain(t *testing.T) {
111113
loadCfgDeps := mocks.NewLoadSystemDeps(ctrl)
112114
mem := mocks.NewMemory(ctrl)
113115
fs := afero.NewMemMapFs()
116+
stdOut := os.Stdout
114117
tc.mockSvc(logger, ffd, fs, loadCfgDeps, mem)
115-
err := xmain(logger, ffd, fs, loadCfgDeps, mem)
118+
err := xmain(logger, ffd, fs, loadCfgDeps, mem, stdOut)
116119
assert.Equal(t, err, tc.wantErr)
117120
})
118121
}
@@ -125,13 +128,14 @@ func TestNewApp(t *testing.T) {
125128
l := mocks.NewLogger(ctrl)
126129
fp := path.Finch("")
127130
fs := afero.NewMemMapFs()
131+
stdOut := os.Stdout
128132

129133
require.NoError(t, afero.WriteFile(fs, "/real/config.yaml", []byte(configStr), 0o600))
130134

131-
cmd := newApp(l, fp, fs, &config.Finch{})
135+
cmd := newApp(l, fp, fs, &config.Finch{}, stdOut)
132136

133137
assert.Equal(t, cmd.Name(), finchRootCmd)
134-
assert.Equal(t, cmd.Version, finchVersion)
138+
assert.Equal(t, cmd.Version, version.Version)
135139
assert.Equal(t, cmd.SilenceUsage, true)
136140
assert.Equal(t, cmd.SilenceErrors, true)
137141
// confirm the number of command, comprised of nerdctl commands + finch commands (version, vm)

cmd/finch/version.go

Lines changed: 101 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,122 @@
44
package main
55

66
import (
7+
"encoding/json"
8+
"errors"
79
"fmt"
10+
"io"
811

912
"github.com/spf13/cobra"
1013

14+
"github.com/runfinch/finch/pkg/command"
15+
"github.com/runfinch/finch/pkg/flog"
16+
"github.com/runfinch/finch/pkg/lima"
1117
"github.com/runfinch/finch/pkg/version"
1218
)
1319

14-
var finchVersion = version.Version
15-
16-
func newVersionCommand() *cobra.Command {
20+
func newVersionCommand(limaCmdCreator command.LimaCmdCreator, logger flog.Logger, stdOut io.Writer) *cobra.Command {
1721
versionCommand := &cobra.Command{
1822
Use: "version",
1923
Args: cobra.NoArgs,
2024
Short: "Shows Finch version information",
21-
RunE: versionAction,
25+
RunE: newVersionAction(limaCmdCreator, logger, stdOut).runAdapter,
2226
}
2327

2428
return versionCommand
2529
}
2630

27-
func versionAction(cmd *cobra.Command, args []string) error {
28-
fmt.Println("Finch version:", finchVersion)
31+
type versionAction struct {
32+
creator command.LimaCmdCreator
33+
logger flog.Logger
34+
stdOut io.Writer
35+
}
36+
37+
// NerdctlVersionOutput captures the nerdctl version.
38+
type NerdctlVersionOutput struct {
39+
Client NerdctlClientOuput `json:"Client"`
40+
Server NerdctlServerOutput `json:"Server"`
41+
}
42+
43+
// NerdctlClientOuput captures the nerdctl Client output.
44+
type NerdctlClientOuput struct {
45+
Version string `json:"Version"`
46+
GitCommit string `json:"GitCommit"`
47+
GoVersion string `json:"GoVersion"`
48+
Os string `json:"Os"`
49+
Arch string `json:"Arch"`
50+
Components []NerdctlComponentsOutput `json:"Components"`
51+
}
52+
53+
// NerdctlServerOutput captures the nerdctl Server output.
54+
type NerdctlServerOutput struct {
55+
Components []NerdctlComponentsOutput `json:"Components"`
56+
}
57+
58+
// NerdctlComponentsOutput captures the nerdctl components output.
59+
type NerdctlComponentsOutput struct {
60+
Name string `json:"Name"`
61+
Version string `json:"Version"`
62+
Details struct {
63+
GitCommit string `json:"GitCommit"`
64+
}
65+
}
66+
67+
func newVersionAction(creator command.LimaCmdCreator, logger flog.Logger, stdOut io.Writer) *versionAction {
68+
return &versionAction{creator: creator, logger: logger, stdOut: stdOut}
69+
}
70+
71+
func (va *versionAction) runAdapter(cmd *cobra.Command, args []string) error {
72+
return va.run()
73+
}
74+
75+
func (va *versionAction) run() error {
76+
status, err := lima.GetVMStatus(va.creator, va.logger, limaInstanceName)
77+
if err != nil {
78+
va.printVersion()
79+
return fmt.Errorf("failed to get VM status: %w", err)
80+
}
81+
if status != lima.Running {
82+
va.printVersion()
83+
return errors.New("detailed version info is unavailable because VM is not running")
84+
}
85+
86+
limaArgs := []string{"shell", limaInstanceName, "nerdctl", "version", "--format", "json"}
87+
out, err := va.creator.CreateWithoutStdio(limaArgs...).Output()
88+
if err != nil {
89+
return fmt.Errorf("failed to create the nerdctl version command: %w", err)
90+
}
91+
92+
var nerdctlVersion NerdctlVersionOutput
93+
err = json.Unmarshal(out, &nerdctlVersion)
94+
95+
if err != nil {
96+
va.printVersion()
97+
return fmt.Errorf("failed to JSON-unmarshal the nerdctl version output: %w", err)
98+
}
99+
100+
fmt.Fprintf(va.stdOut, "Client:\n")
101+
fmt.Fprintf(va.stdOut, " Version:\t%s\n", version.Version)
102+
fmt.Fprintf(va.stdOut, " OS/Arch:\t%s/%s\n", nerdctlVersion.Client.Os, nerdctlVersion.Client.Arch)
103+
fmt.Fprintf(va.stdOut, " GitCommit:\t%s\n", version.GitCommit)
104+
fmt.Fprintf(va.stdOut, " nerdctl:\n")
105+
fmt.Fprintf(va.stdOut, " Version:\t%s\n", nerdctlVersion.Client.Version)
106+
fmt.Fprintf(va.stdOut, " GitCommit:\t%s\n", nerdctlVersion.Client.GitCommit)
107+
for _, compo := range nerdctlVersion.Client.Components {
108+
fmt.Fprintf(va.stdOut, " %s:\n", compo.Name)
109+
fmt.Fprintf(va.stdOut, " Version:\t%s\n", compo.Version)
110+
fmt.Fprintf(va.stdOut, " GitCommit:\t%s\n", compo.Details.GitCommit)
111+
}
112+
fmt.Fprintf(va.stdOut, "\n")
113+
fmt.Fprintf(va.stdOut, "Server:\n")
114+
for _, compo := range nerdctlVersion.Server.Components {
115+
fmt.Fprintf(va.stdOut, " %s:\n", compo.Name)
116+
fmt.Fprintf(va.stdOut, " Version:\t%s\n", compo.Version)
117+
fmt.Fprintf(va.stdOut, " GitCommit:\t%s\n", compo.Details.GitCommit)
118+
}
119+
29120
return nil
30121
}
122+
123+
func (va *versionAction) printVersion() {
124+
(fmt.Fprintf(va.stdOut, "Finch version:\t%s\n", version.Version))
125+
}

0 commit comments

Comments
 (0)