Skip to content

Commit

Permalink
feat(cli): add command to interogate the server version and other det…
Browse files Browse the repository at this point in the history
…ails

Signed-off-by: Laurentiu Niculae <[email protected]>
  • Loading branch information
laurentiuNiculae committed Oct 25, 2023
1 parent a3d8202 commit 95d3d33
Show file tree
Hide file tree
Showing 9 changed files with 233 additions and 6 deletions.
3 changes: 2 additions & 1 deletion errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ var (
ErrUnauthorizedAccess = errors.New("auth: unauthorized access. check credentials")
ErrCannotResetConfigKey = errors.New("cli: cannot reset given config key")
ErrConfigNotFound = errors.New("cli: config with the given name does not exist")
ErrNoURLProvided = errors.New("cli: no URL provided in argument or via config")
ErrNoURLProvided = errors.New("cli: no URL provided by flag or via config")
ErrIllegalConfigKey = errors.New("cli: given config key is not allowed")
ErrScanNotSupported = errors.New("search: scanning of image media type not supported")
ErrCLITimeout = errors.New("cli: Query timed out while waiting for results")
Expand Down Expand Up @@ -157,6 +157,7 @@ var (
ErrGQLEndpointNotFound = errors.New("cli: the server doesn't have a gql endpoint")
ErrGQLQueryNotSupported = errors.New("cli: query is not supported or has different arguments")
ErrBadHTTPStatusCode = errors.New("cli: the response doesn't contain the expected status code")
ErrFormatNotSupported = errors.New("cli: the given output format is not supported")
ErrFileAlreadyCancelled = errors.New("storageDriver: file already cancelled")
ErrFileAlreadyClosed = errors.New("storageDriver: file already closed")
ErrFileAlreadyCommitted = errors.New("storageDriver: file already committed")
Expand Down
1 change: 1 addition & 0 deletions pkg/cli/client/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ func enableCli(rootCmd *cobra.Command) {
rootCmd.AddCommand(NewCVECommand(NewSearchService()))
rootCmd.AddCommand(NewRepoCommand(NewSearchService()))
rootCmd.AddCommand(NewSearchCommand(NewSearchService()))
rootCmd.AddCommand(NewServerInfoCommand())
}
111 changes: 111 additions & 0 deletions pkg/cli/client/server_info_cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//go:build search
// +build search

package client

import (
"context"
"encoding/json"
"fmt"
"strings"

"github.com/spf13/cobra"
"gopkg.in/yaml.v2"

zerr "zotregistry.io/zot/errors"
"zotregistry.io/zot/pkg/api/constants"
"zotregistry.io/zot/pkg/cli/cmdflags"

Check failure on line 17 in pkg/cli/client/server_info_cmd.go

View workflow job for this annotation

GitHub Actions / Run zot with extensions tests

no required module provides package zotregistry.io/zot/pkg/cli/cmdflags; to add it:

Check failure on line 17 in pkg/cli/client/server_info_cmd.go

View workflow job for this annotation

GitHub Actions / Running privileged tests on Linux

no required module provides package zotregistry.io/zot/pkg/cli/cmdflags; to add it:
)

func NewServerInfoCommand() *cobra.Command {
serverInfoCmd := &cobra.Command{
Use: "server-info",
Short: "Information about the server configuration and build information",
Long: `Information about the server configuration and build information`,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
searchConfig, err := GetSearchConfigFromFlags(cmd, NewSearchService())
if err != nil {
return err
}

return GetServerInfo(searchConfig)
},
}

serverInfoCmd.Flags().String(cmdflags.OutputFormatFlag, "text", "Specify the output format [text|json|yaml]")

return serverInfoCmd
}

func GetServerInfo(config searchConfig) error {

Check failure on line 41 in pkg/cli/client/server_info_cmd.go

View workflow job for this annotation

GitHub Actions / lint

undefined: searchConfig (typecheck)
username, password := getUsernameAndPassword(config.user)
ctx := context.Background()

mgmtEndpoint, err := combineServerAndEndpointURL(config.servURL, fmt.Sprintf("%s%s",
constants.RoutePrefix, constants.ExtMgmt))
if err != nil {
return err
}

serverInfo := ServerInfo{}

_, err = makeGETRequest(ctx, mgmtEndpoint, username, password, config.verifyTLS, config.debug,
&serverInfo, config.resultWriter)
if err != nil {
return err
}

outputResult, err := serverInfo.ToStringFormat(config.outputFormat)
if err != nil {
return err
}

fmt.Fprintln(config.resultWriter, outputResult)

return nil
}

type ServerInfo struct {
DistSpecVersion string `json:"distSpecVersion" mapstructure:"distSpecVersion"`
Commit string `json:"commit" mapstructure:"commit"`
BinaryType string `json:"binaryType" mapstructure:"binaryType"`
ReleaseTag string `json:"releaseTag" mapstructure:"releaseTag"`
}

func (si *ServerInfo) ToStringFormat(format string) (string, error) {
switch format {
case "text", "":
return si.ToText()
case "json":
return si.ToJSON()
case "yaml", "yml":
return si.ToYAML()
default:
return "", zerr.ErrFormatNotSupported
}
}

func (si *ServerInfo) ToText() (string, error) {
flagsList := strings.Split(strings.Trim(si.BinaryType, "-"), "-")
flags := strings.Join(flagsList, ", ")

return fmt.Sprintf("Server Version: %s\n"+
"Dist Spec Version: %s\n"+
"Built with: %s",
si.ReleaseTag, si.DistSpecVersion, flags,
),
nil
}

func (si *ServerInfo) ToJSON() (string, error) {
blob, err := json.MarshalIndent(*si, "", " ")

return string(blob), err
}

func (si *ServerInfo) ToYAML() (string, error) {
body, err := yaml.Marshal(*si)

return string(body), err
}
99 changes: 99 additions & 0 deletions pkg/cli/client/server_info_cmd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//go:build search
// +build search

package client //nolint:testpackage

import (
"bytes"
"fmt"
"os"
"regexp"
"strings"
"testing"

. "github.com/smartystreets/goconvey/convey"

"zotregistry.io/zot/pkg/api"
"zotregistry.io/zot/pkg/api/config"
extconf "zotregistry.io/zot/pkg/extensions/config"
test "zotregistry.io/zot/pkg/test/common"
)

func TestServerInfoCommand(t *testing.T) {
Convey("ServerInfoCommand", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
conf.Storage.GC = false
defaultVal := true
conf.Extensions = &extconf.ExtensionConfig{
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
}

ctlr := api.NewController(conf)
ctlr.Config.Storage.RootDirectory = t.TempDir()
cm := test.NewControllerManager(ctlr)

cm.StartAndWait(conf.HTTP.Port)
defer cm.StopServer()

configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"server-info-test","url":"%s","showspinner":false}]}`,
baseURL))
defer os.Remove(configPath)

args := []string{"server-info", "--config", "server-info-test"}
cmd := NewCliRootCmd()
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldBeNil)
space := regexp.MustCompile(`\s+`)
str := space.ReplaceAllString(buff.String(), " ")
actual := strings.TrimSpace(str)
So(actual, ShouldContainSubstring, config.ReleaseTag)
So(actual, ShouldContainSubstring, config.BinaryType)

// JSON
args = []string{"server-info", "--config", "server-info-test", "--format", "json"}
cmd = NewCliRootCmd()
buff = bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldBeNil)
space = regexp.MustCompile(`\s+`)
str = space.ReplaceAllString(buff.String(), " ")
actual = strings.TrimSpace(str)
So(actual, ShouldContainSubstring, config.ReleaseTag)
So(actual, ShouldContainSubstring, config.BinaryType)

// YAML
args = []string{"server-info", "--config", "server-info-test", "--format", "yaml"}
cmd = NewCliRootCmd()
buff = bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldBeNil)
space = regexp.MustCompile(`\s+`)
str = space.ReplaceAllString(buff.String(), " ")
actual = strings.TrimSpace(str)
So(actual, ShouldContainSubstring, config.ReleaseTag)
So(actual, ShouldContainSubstring, config.BinaryType)

// bad type
args = []string{"server-info", "--config", "server-info-test", "--format", "badType"}
cmd = NewCliRootCmd()
buff = bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
})
}
5 changes: 1 addition & 4 deletions pkg/cli/server/extensions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1178,7 +1178,7 @@ func TestServeMgmtExtension(t *testing.T) {
So(found, ShouldBeTrue)
})

Convey("Mgmt disabled - search unconfigured", t, func(c C) {
Convey("Mgmt disabled - Search unconfigured", t, func(c C) {
content := `{
"storage": {
"rootDirectory": "%s"
Expand All @@ -1192,9 +1192,6 @@ func TestServeMgmtExtension(t *testing.T) {
"output": "%s"
},
"extensions": {
"search": {
"enable": false
}
}
}`

Expand Down
4 changes: 3 additions & 1 deletion pkg/extensions/extension_mgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ type Auth struct {

type StrippedConfig struct {
DistSpecVersion string `json:"distSpecVersion" mapstructure:"distSpecVersion"`
BinaryType string `json:"binaryType" mapstructure:"binaryType"`
Commit string `json:"commit" mapstructure:"commit"`

Check failure on line 46 in pkg/extensions/extension_mgmt.go

View workflow job for this annotation

GitHub Actions / lint

tag is not aligned, should be: json:"commit" mapstructure:"commit" (tagalign)
ReleaseTag string `json:"releaseTag" mapstructure:"releaseTag"`

Check failure on line 47 in pkg/extensions/extension_mgmt.go

View workflow job for this annotation

GitHub Actions / lint

tag is not aligned, should be: json:"releaseTag" mapstructure:"releaseTag" (tagalign)
BinaryType string `json:"binaryType" mapstructure:"binaryType"`
HTTP struct {
Auth *Auth `json:"auth,omitempty" mapstructure:"auth"`
} `json:"http" mapstructure:"http"`
Expand Down
6 changes: 6 additions & 0 deletions swagger/docs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions swagger/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -1382,6 +1382,9 @@
"binaryType": {
"type": "string"
},
"commit": {
"type": "string"
},
"distSpecVersion": {
"type": "string"
},
Expand All @@ -1392,6 +1395,9 @@
"$ref": "#/definitions/extensions.Auth"
}
}
},
"releaseTag": {
"type": "string"
}
}
},
Expand Down
4 changes: 4 additions & 0 deletions swagger/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,17 @@ definitions:
properties:
binaryType:
type: string
commit:
type: string
distSpecVersion:
type: string
http:
properties:
auth:
$ref: '#/definitions/extensions.Auth'
type: object
releaseTag:
type: string
type: object
github_com_opencontainers_image-spec_specs-go_v1.Descriptor:
properties:
Expand Down

0 comments on commit 95d3d33

Please sign in to comment.