Skip to content

Commit

Permalink
feat: Print version with Client and Server (#108)
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
ahsan-z-khan authored Jan 11, 2023
1 parent 8d06eec commit 7f7cdda
Show file tree
Hide file tree
Showing 9 changed files with 305 additions and 49 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ CORE_OUTDIR := $(CURDIR)/$(CORE_FILENAME)/_output
CORE_VDE_PREFIX ?= $(OUTDIR)/dependencies/vde/opt/finch
LICENSEDIR := $(OUTDIR)/license-files
VERSION := $(shell git describe --match 'v[0-9]*' --dirty='.modified' --always --tags)
LDFLAGS := "-X $(PACKAGE)/pkg/version.Version=$(VERSION)"
GITCOMMIT := $(shell git rev-parse HEAD)$(shell if ! git diff --no-ext-diff --quiet --exit-code; then echo .m; fi)
LDFLAGS := "-X $(PACKAGE)/pkg/version.Version=$(VERSION) -X $(PACKAGE)/pkg/version.GitCommit=$(GITCOMMIT)"

.DEFAULT_GOAL := all

Expand Down
22 changes: 16 additions & 6 deletions cmd/finch/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ package main

import (
"fmt"
"io"
"os"

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

Expand All @@ -18,6 +20,7 @@ import (
"github.com/runfinch/finch/pkg/fssh"
"github.com/runfinch/finch/pkg/path"
"github.com/runfinch/finch/pkg/system"
"github.com/runfinch/finch/pkg/version"

"github.com/spf13/afero"
"github.com/spf13/cobra"
Expand All @@ -30,12 +33,19 @@ func main() {
stdLib := system.NewStdLib()
fs := afero.NewOsFs()
mem := fmemory.NewMemory()
if err := xmain(logger, stdLib, fs, stdLib, mem); err != nil {
stdOut := os.Stdout
if err := xmain(logger, stdLib, fs, stdLib, mem, stdOut); err != nil {
logger.Fatal(err)
}
}

func xmain(logger flog.Logger, ffd path.FinchFinderDeps, fs afero.Fs, loadCfgDeps config.LoadSystemDeps, mem fmemory.Memory) error {
func xmain(logger flog.Logger,
ffd path.FinchFinderDeps,
fs afero.Fs,
loadCfgDeps config.LoadSystemDeps,
mem fmemory.Memory,
stdOut io.Writer,
) error {
fp, err := path.FindFinch(ffd)
if err != nil {
return fmt.Errorf("failed to find the installation path of Finch: %w", err)
Expand All @@ -46,17 +56,17 @@ func xmain(logger flog.Logger, ffd path.FinchFinderDeps, fs afero.Fs, loadCfgDep
return fmt.Errorf("failed to load config: %w", err)
}

return newApp(logger, fp, fs, fc).Execute()
return newApp(logger, fp, fs, fc, stdOut).Execute()
}

var newApp = func(logger flog.Logger, fp path.Finch, fs afero.Fs, fc *config.Finch) *cobra.Command {
var newApp = func(logger flog.Logger, fp path.Finch, fs afero.Fs, fc *config.Finch, stdOut io.Writer) *cobra.Command {
usage := fmt.Sprintf("%v <command>", finchRootCmd)
rootCmd := &cobra.Command{
Use: usage,
Short: "Finch: open-source container development tool",
SilenceUsage: true,
SilenceErrors: true,
Version: finchVersion,
Version: version.Version,
}
// TODO: Decide when to forward --debug to the dependencies
// (e.g. nerdctl for container commands and limactl for VM commands).
Expand All @@ -83,7 +93,7 @@ var newApp = func(logger flog.Logger, fp path.Finch, fs afero.Fs, fc *config.Fin
allCommands := initializeNerdctlCommands(lcc, logger)
// append finch specific commands
allCommands = append(allCommands,
newVersionCommand(),
newVersionCommand(lcc, logger, stdOut),
virtualMachineCommands(logger, fp, lcc, ecc, fs, fc),
)

Expand Down
10 changes: 7 additions & 3 deletions cmd/finch/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package main
import (
"errors"
"fmt"
"os"
"testing"

"gopkg.in/yaml.v3"
Expand All @@ -14,6 +15,7 @@ import (
"github.com/runfinch/finch/pkg/flog"
"github.com/runfinch/finch/pkg/mocks"
"github.com/runfinch/finch/pkg/path"
"github.com/runfinch/finch/pkg/version"

"github.com/golang/mock/gomock"
"github.com/spf13/afero"
Expand Down Expand Up @@ -111,8 +113,9 @@ func TestXmain(t *testing.T) {
loadCfgDeps := mocks.NewLoadSystemDeps(ctrl)
mem := mocks.NewMemory(ctrl)
fs := afero.NewMemMapFs()
stdOut := os.Stdout
tc.mockSvc(logger, ffd, fs, loadCfgDeps, mem)
err := xmain(logger, ffd, fs, loadCfgDeps, mem)
err := xmain(logger, ffd, fs, loadCfgDeps, mem, stdOut)
assert.Equal(t, err, tc.wantErr)
})
}
Expand All @@ -125,13 +128,14 @@ func TestNewApp(t *testing.T) {
l := mocks.NewLogger(ctrl)
fp := path.Finch("")
fs := afero.NewMemMapFs()
stdOut := os.Stdout

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

cmd := newApp(l, fp, fs, &config.Finch{})
cmd := newApp(l, fp, fs, &config.Finch{}, stdOut)

assert.Equal(t, cmd.Name(), finchRootCmd)
assert.Equal(t, cmd.Version, finchVersion)
assert.Equal(t, cmd.Version, version.Version)
assert.Equal(t, cmd.SilenceUsage, true)
assert.Equal(t, cmd.SilenceErrors, true)
// confirm the number of command, comprised of nerdctl commands + finch commands (version, vm)
Expand Down
107 changes: 101 additions & 6 deletions cmd/finch/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,122 @@
package main

import (
"encoding/json"
"errors"
"fmt"
"io"

"github.com/spf13/cobra"

"github.com/runfinch/finch/pkg/command"
"github.com/runfinch/finch/pkg/flog"
"github.com/runfinch/finch/pkg/lima"
"github.com/runfinch/finch/pkg/version"
)

var finchVersion = version.Version

func newVersionCommand() *cobra.Command {
func newVersionCommand(limaCmdCreator command.LimaCmdCreator, logger flog.Logger, stdOut io.Writer) *cobra.Command {
versionCommand := &cobra.Command{
Use: "version",
Args: cobra.NoArgs,
Short: "Shows Finch version information",
RunE: versionAction,
RunE: newVersionAction(limaCmdCreator, logger, stdOut).runAdapter,
}

return versionCommand
}

func versionAction(cmd *cobra.Command, args []string) error {
fmt.Println("Finch version:", finchVersion)
type versionAction struct {
creator command.LimaCmdCreator
logger flog.Logger
stdOut io.Writer
}

// NerdctlVersionOutput captures the nerdctl version.
type NerdctlVersionOutput struct {
Client NerdctlClientOuput `json:"Client"`
Server NerdctlServerOutput `json:"Server"`
}

// NerdctlClientOuput captures the nerdctl Client output.
type NerdctlClientOuput struct {
Version string `json:"Version"`
GitCommit string `json:"GitCommit"`
GoVersion string `json:"GoVersion"`
Os string `json:"Os"`
Arch string `json:"Arch"`
Components []NerdctlComponentsOutput `json:"Components"`
}

// NerdctlServerOutput captures the nerdctl Server output.
type NerdctlServerOutput struct {
Components []NerdctlComponentsOutput `json:"Components"`
}

// NerdctlComponentsOutput captures the nerdctl components output.
type NerdctlComponentsOutput struct {
Name string `json:"Name"`
Version string `json:"Version"`
Details struct {
GitCommit string `json:"GitCommit"`
}
}

func newVersionAction(creator command.LimaCmdCreator, logger flog.Logger, stdOut io.Writer) *versionAction {
return &versionAction{creator: creator, logger: logger, stdOut: stdOut}
}

func (va *versionAction) runAdapter(cmd *cobra.Command, args []string) error {
return va.run()
}

func (va *versionAction) run() error {
status, err := lima.GetVMStatus(va.creator, va.logger, limaInstanceName)
if err != nil {
va.printVersion()
return fmt.Errorf("failed to get VM status: %w", err)
}
if status != lima.Running {
va.printVersion()
return errors.New("detailed version info is unavailable because VM is not running")
}

limaArgs := []string{"shell", limaInstanceName, "nerdctl", "version", "--format", "json"}
out, err := va.creator.CreateWithoutStdio(limaArgs...).Output()
if err != nil {
return fmt.Errorf("failed to create the nerdctl version command: %w", err)
}

var nerdctlVersion NerdctlVersionOutput
err = json.Unmarshal(out, &nerdctlVersion)

if err != nil {
va.printVersion()
return fmt.Errorf("failed to JSON-unmarshal the nerdctl version output: %w", err)
}

fmt.Fprintf(va.stdOut, "Client:\n")
fmt.Fprintf(va.stdOut, " Version:\t%s\n", version.Version)
fmt.Fprintf(va.stdOut, " OS/Arch:\t%s/%s\n", nerdctlVersion.Client.Os, nerdctlVersion.Client.Arch)
fmt.Fprintf(va.stdOut, " GitCommit:\t%s\n", version.GitCommit)
fmt.Fprintf(va.stdOut, " nerdctl:\n")
fmt.Fprintf(va.stdOut, " Version:\t%s\n", nerdctlVersion.Client.Version)
fmt.Fprintf(va.stdOut, " GitCommit:\t%s\n", nerdctlVersion.Client.GitCommit)
for _, compo := range nerdctlVersion.Client.Components {
fmt.Fprintf(va.stdOut, " %s:\n", compo.Name)
fmt.Fprintf(va.stdOut, " Version:\t%s\n", compo.Version)
fmt.Fprintf(va.stdOut, " GitCommit:\t%s\n", compo.Details.GitCommit)
}
fmt.Fprintf(va.stdOut, "\n")
fmt.Fprintf(va.stdOut, "Server:\n")
for _, compo := range nerdctlVersion.Server.Components {
fmt.Fprintf(va.stdOut, " %s:\n", compo.Name)
fmt.Fprintf(va.stdOut, " Version:\t%s\n", compo.Version)
fmt.Fprintf(va.stdOut, " GitCommit:\t%s\n", compo.Details.GitCommit)
}

return nil
}

func (va *versionAction) printVersion() {
(fmt.Fprintf(va.stdOut, "Finch version:\t%s\n", version.Version))
}
Loading

0 comments on commit 7f7cdda

Please sign in to comment.