Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Austin Vazquez <austin.vazquez@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -5,7 +5,6 @@ import ( |
| 5 | 5 |
"io" |
| 6 | 6 |
"net" |
| 7 | 7 |
|
| 8 |
- "github.com/moby/moby/api/types" |
|
| 9 | 8 |
"github.com/moby/moby/api/types/network" |
| 10 | 9 |
"github.com/moby/moby/api/types/system" |
| 11 | 10 |
) |
| ... | ... |
@@ -27,7 +26,7 @@ type stableAPIClient interface {
|
| 27 | 27 |
VolumeAPIClient |
| 28 | 28 |
ClientVersion() string |
| 29 | 29 |
DaemonHost() string |
| 30 |
- ServerVersion(ctx context.Context) (types.Version, error) |
|
| 30 |
+ ServerVersion(ctx context.Context, options ServerVersionOptions) (ServerVersionResult, error) |
|
| 31 | 31 |
HijackDialer |
| 32 | 32 |
Dialer() func(context.Context) (net.Conn, error) |
| 33 | 33 |
Close() error |
| ... | ... |
@@ -7,15 +7,56 @@ import ( |
| 7 | 7 |
"github.com/moby/moby/api/types" |
| 8 | 8 |
) |
| 9 | 9 |
|
| 10 |
-// ServerVersion returns information of the docker client and server host. |
|
| 11 |
-func (cli *Client) ServerVersion(ctx context.Context) (types.Version, error) {
|
|
| 10 |
+// ServerVersionOptions specifies options for the server version request. |
|
| 11 |
+type ServerVersionOptions struct {
|
|
| 12 |
+ // Currently no options are supported. |
|
| 13 |
+} |
|
| 14 |
+ |
|
| 15 |
+// ServerVersionResult contains information about the Docker server host. |
|
| 16 |
+type ServerVersionResult struct {
|
|
| 17 |
+ // Platform is the platform (product name) the server is running on. |
|
| 18 |
+ Platform PlatformInfo |
|
| 19 |
+ |
|
| 20 |
+ // APIVersion is the highest API version supported by the server. |
|
| 21 |
+ APIVersion string |
|
| 22 |
+ |
|
| 23 |
+ // MinAPIVersion is the minimum API version the server supports. |
|
| 24 |
+ MinAPIVersion string |
|
| 25 |
+ |
|
| 26 |
+ // Components contains version information for the components making |
|
| 27 |
+ // up the server. Information in this field is for informational |
|
| 28 |
+ // purposes, and not part of the API contract. |
|
| 29 |
+ Components []types.ComponentVersion |
|
| 30 |
+} |
|
| 31 |
+ |
|
| 32 |
+// PlatformInfo holds information about the platform (product name) the |
|
| 33 |
+// server is running on. |
|
| 34 |
+type PlatformInfo struct {
|
|
| 35 |
+ // Name is the name of the platform (for example, "Docker Engine - Community", |
|
| 36 |
+ // or "Docker Desktop 4.49.0 (208003)") |
|
| 37 |
+ Name string |
|
| 38 |
+} |
|
| 39 |
+ |
|
| 40 |
+// ServerVersion returns information of the Docker server host. |
|
| 41 |
+func (cli *Client) ServerVersion(ctx context.Context, _ ServerVersionOptions) (ServerVersionResult, error) {
|
|
| 12 | 42 |
resp, err := cli.get(ctx, "/version", nil, nil) |
| 13 | 43 |
defer ensureReaderClosed(resp) |
| 14 | 44 |
if err != nil {
|
| 15 |
- return types.Version{}, err
|
|
| 45 |
+ return ServerVersionResult{}, err
|
|
| 46 |
+ } |
|
| 47 |
+ |
|
| 48 |
+ var v types.Version |
|
| 49 |
+ err = json.NewDecoder(resp.Body).Decode(&v) |
|
| 50 |
+ if err != nil {
|
|
| 51 |
+ return ServerVersionResult{}, err
|
|
| 16 | 52 |
} |
| 17 | 53 |
|
| 18 |
- var server types.Version |
|
| 19 |
- err = json.NewDecoder(resp.Body).Decode(&server) |
|
| 20 |
- return server, err |
|
| 54 |
+ return ServerVersionResult{
|
|
| 55 |
+ Platform: PlatformInfo{
|
|
| 56 |
+ Name: v.Platform.Name, |
|
| 57 |
+ }, |
|
| 58 |
+ APIVersion: v.APIVersion, |
|
| 59 |
+ MinAPIVersion: v.MinAPIVersion, |
|
| 60 |
+ Components: v.Components, |
|
| 61 |
+ }, nil |
|
| 21 | 62 |
} |
| ... | ... |
@@ -43,11 +43,11 @@ func OnlyDefaultNetworks(ctx context.Context) bool {
|
| 43 | 43 |
} |
| 44 | 44 |
|
| 45 | 45 |
func IsAmd64() bool {
|
| 46 |
- return testEnv.DaemonVersion.Arch == "amd64" |
|
| 46 |
+ return testEnv.DaemonInfo.Architecture == "amd64" |
|
| 47 | 47 |
} |
| 48 | 48 |
|
| 49 | 49 |
func NotPpc64le() bool {
|
| 50 |
- return testEnv.DaemonVersion.Arch != "ppc64le" |
|
| 50 |
+ return testEnv.DaemonInfo.Architecture != "ppc64le" |
|
| 51 | 51 |
} |
| 52 | 52 |
|
| 53 | 53 |
func UnixCli() bool {
|
| ... | ... |
@@ -953,7 +953,7 @@ func TestEmptyPortBindingsBC(t *testing.T) {
|
| 953 | 953 |
|
| 954 | 954 |
// Skip this subtest if the daemon doesn't support the client version. |
| 955 | 955 |
// TODO(aker): drop this once the Engine supports API version >= 1.53 |
| 956 |
- _, err := apiClient.ServerVersion(ctx) |
|
| 956 |
+ _, err := apiClient.ServerVersion(ctx, client.ServerVersionOptions{})
|
|
| 957 | 957 |
if err != nil && strings.Contains(err.Error(), fmt.Sprintf("client version %s is too new", version)) {
|
| 958 | 958 |
t.Skipf("requires API %s", version)
|
| 959 | 959 |
} |
| ... | ... |
@@ -106,7 +106,7 @@ func TestAuthZPluginAllowRequest(t *testing.T) {
|
| 106 | 106 |
assertURIRecorded(t, ctrl.requestsURIs, "/containers/create") |
| 107 | 107 |
assertURIRecorded(t, ctrl.requestsURIs, fmt.Sprintf("/containers/%s/start", cID))
|
| 108 | 108 |
|
| 109 |
- _, err := c.ServerVersion(ctx) |
|
| 109 |
+ _, err := c.ServerVersion(ctx, client.ServerVersionOptions{})
|
|
| 110 | 110 |
assert.NilError(t, err) |
| 111 | 111 |
assert.Equal(t, 1, ctrl.versionReqCount) |
| 112 | 112 |
assert.Equal(t, 1, ctrl.versionResCount) |
| ... | ... |
@@ -137,7 +137,7 @@ func TestAuthZPluginTLS(t *testing.T) {
|
| 137 | 137 |
c, err := newTLSAPIClient(testDaemonHTTPSAddr, cacertPath, clientCertPath, clientKeyPath) |
| 138 | 138 |
assert.NilError(t, err) |
| 139 | 139 |
|
| 140 |
- _, err = c.ServerVersion(ctx) |
|
| 140 |
+ _, err = c.ServerVersion(ctx, client.ServerVersionOptions{})
|
|
| 141 | 141 |
assert.NilError(t, err) |
| 142 | 142 |
|
| 143 | 143 |
assert.Equal(t, "client", ctrl.reqUser) |
| ... | ... |
@@ -165,7 +165,7 @@ func TestAuthZPluginDenyRequest(t *testing.T) {
|
| 165 | 165 |
c := d.NewClientT(t) |
| 166 | 166 |
|
| 167 | 167 |
// Ensure command is blocked |
| 168 |
- _, err := c.ServerVersion(ctx) |
|
| 168 |
+ _, err := c.ServerVersion(ctx, client.ServerVersionOptions{})
|
|
| 169 | 169 |
assert.Assert(t, err != nil) |
| 170 | 170 |
assert.Equal(t, 1, ctrl.versionReqCount) |
| 171 | 171 |
assert.Equal(t, 0, ctrl.versionResCount) |
| ... | ... |
@@ -211,7 +211,7 @@ func TestAuthZPluginDenyResponse(t *testing.T) {
|
| 211 | 211 |
c := d.NewClientT(t) |
| 212 | 212 |
|
| 213 | 213 |
// Ensure command is blocked |
| 214 |
- _, err := c.ServerVersion(ctx) |
|
| 214 |
+ _, err := c.ServerVersion(ctx, client.ServerVersionOptions{})
|
|
| 215 | 215 |
assert.Assert(t, err != nil) |
| 216 | 216 |
assert.Equal(t, 1, ctrl.versionReqCount) |
| 217 | 217 |
assert.Equal(t, 1, ctrl.versionResCount) |
| ... | ... |
@@ -304,7 +304,7 @@ func TestAuthZPluginErrorResponse(t *testing.T) {
|
| 304 | 304 |
c := d.NewClientT(t) |
| 305 | 305 |
|
| 306 | 306 |
// Ensure command is blocked |
| 307 |
- _, err := c.ServerVersion(ctx) |
|
| 307 |
+ _, err := c.ServerVersion(ctx, client.ServerVersionOptions{})
|
|
| 308 | 308 |
assert.Assert(t, err != nil) |
| 309 | 309 |
assert.Equal(t, fmt.Sprintf("Error response from daemon: plugin %s failed with error: %s: %s", testAuthZPlugin, authorization.AuthZApiResponse, errorMessage), err.Error())
|
| 310 | 310 |
} |
| ... | ... |
@@ -317,7 +317,7 @@ func TestAuthZPluginErrorRequest(t *testing.T) {
|
| 317 | 317 |
c := d.NewClientT(t) |
| 318 | 318 |
|
| 319 | 319 |
// Ensure command is blocked |
| 320 |
- _, err := c.ServerVersion(ctx) |
|
| 320 |
+ _, err := c.ServerVersion(ctx, client.ServerVersionOptions{})
|
|
| 321 | 321 |
assert.Assert(t, err != nil) |
| 322 | 322 |
assert.Equal(t, fmt.Sprintf("Error response from daemon: plugin %s failed with error: %s: %s", testAuthZPlugin, authorization.AuthZApiRequest, errorMessage), err.Error())
|
| 323 | 323 |
} |
| ... | ... |
@@ -331,7 +331,7 @@ func TestAuthZPluginEnsureNoDuplicatePluginRegistration(t *testing.T) {
|
| 331 | 331 |
|
| 332 | 332 |
c := d.NewClientT(t) |
| 333 | 333 |
|
| 334 |
- _, err := c.ServerVersion(ctx) |
|
| 334 |
+ _, err := c.ServerVersion(ctx, client.ServerVersionOptions{})
|
|
| 335 | 335 |
assert.NilError(t, err) |
| 336 | 336 |
|
| 337 | 337 |
// assert plugin is only called once.. |
| ... | ... |
@@ -6,6 +6,7 @@ import ( |
| 6 | 6 |
"strings" |
| 7 | 7 |
"testing" |
| 8 | 8 |
|
| 9 |
+ "github.com/moby/moby/api/types" |
|
| 9 | 10 |
"github.com/moby/moby/client" |
| 10 | 11 |
"github.com/moby/moby/v2/internal/testutil/request" |
| 11 | 12 |
"gotest.tools/v3/assert" |
| ... | ... |
@@ -16,26 +17,45 @@ func TestVersion(t *testing.T) {
|
| 16 | 16 |
ctx := setupTest(t) |
| 17 | 17 |
apiClient := testEnv.APIClient() |
| 18 | 18 |
|
| 19 |
- version, err := apiClient.ServerVersion(ctx) |
|
| 19 |
+ version, err := apiClient.ServerVersion(ctx, client.ServerVersionOptions{})
|
|
| 20 | 20 |
assert.NilError(t, err) |
| 21 |
+ assert.Check(t, len(version.Components) > 0, "expected at least one component in version.Components") |
|
| 21 | 22 |
|
| 22 |
- assert.Check(t, version.APIVersion != "") |
|
| 23 |
- assert.Check(t, version.Version != "") |
|
| 24 |
- assert.Check(t, version.MinAPIVersion != "") |
|
| 25 |
- assert.Check(t, is.Equal(testEnv.DaemonInfo.ExperimentalBuild, version.Experimental)) |
|
| 26 |
- assert.Check(t, is.Equal(testEnv.DaemonInfo.OSType, version.Os)) |
|
| 23 |
+ var engine types.ComponentVersion |
|
| 24 |
+ var found bool |
|
| 25 |
+ |
|
| 26 |
+ for _, comp := range version.Components {
|
|
| 27 |
+ if comp.Name == "Engine" {
|
|
| 28 |
+ engine = comp |
|
| 29 |
+ found = true |
|
| 30 |
+ break |
|
| 31 |
+ } |
|
| 32 |
+ } |
|
| 33 |
+ |
|
| 34 |
+ assert.Check(t, found, "Engine component not found in version.Components") |
|
| 35 |
+ assert.Equal(t, engine.Name, "Engine") |
|
| 36 |
+ assert.Check(t, engine.Version != "") |
|
| 37 |
+ assert.Equal(t, engine.Details["ApiVersion"], version.APIVersion) |
|
| 38 |
+ assert.Equal(t, engine.Details["MinAPIVersion"], version.MinAPIVersion) |
|
| 39 |
+ assert.Check(t, is.Equal(testEnv.DaemonInfo.OSType, engine.Details["Os"])) |
|
| 40 |
+ |
|
| 41 |
+ experimentalStr := engine.Details["Experimental"] |
|
| 42 |
+ experimentalBool, err := strconv.ParseBool(experimentalStr) |
|
| 43 |
+ assert.NilError(t, err, "Experimental field in Engine details is not a valid boolean string") |
|
| 44 |
+ assert.Equal(t, testEnv.DaemonInfo.ExperimentalBuild, experimentalBool) |
|
| 27 | 45 |
} |
| 28 | 46 |
|
| 29 | 47 |
func TestAPIClientVersionOldNotSupported(t *testing.T) {
|
| 30 | 48 |
ctx := setupTest(t) |
| 31 |
- major, minor, _ := strings.Cut(testEnv.DaemonVersion.MinAPIVersion, ".") |
|
| 49 |
+ minApiVersion := testEnv.DaemonMinAPIVersion |
|
| 50 |
+ major, minor, _ := strings.Cut(minApiVersion, ".") |
|
| 32 | 51 |
vMinInt, err := strconv.Atoi(minor) |
| 33 | 52 |
assert.NilError(t, err) |
| 34 | 53 |
vMinInt-- |
| 35 | 54 |
version := fmt.Sprintf("%s.%d", major, vMinInt)
|
| 36 | 55 |
apiClient := request.NewAPIClient(t, client.WithVersion(version)) |
| 37 | 56 |
|
| 38 |
- expectedErrorMessage := fmt.Sprintf("Error response from daemon: client version %s is too old. Minimum supported API version is %s, please upgrade your client to a newer version", version, testEnv.DaemonVersion.MinAPIVersion)
|
|
| 39 |
- _, err = apiClient.ServerVersion(ctx) |
|
| 57 |
+ expectedErrorMessage := fmt.Sprintf("Error response from daemon: client version %s is too old. Minimum supported API version is %s, please upgrade your client to a newer version", version, minApiVersion)
|
|
| 58 |
+ _, err = apiClient.ServerVersion(ctx, client.ServerVersionOptions{})
|
|
| 40 | 59 |
assert.Error(t, err, expectedErrorMessage) |
| 41 | 60 |
} |
| ... | ... |
@@ -9,7 +9,6 @@ import ( |
| 9 | 9 |
"strings" |
| 10 | 10 |
"testing" |
| 11 | 11 |
|
| 12 |
- "github.com/moby/moby/api/types" |
|
| 13 | 12 |
"github.com/moby/moby/api/types/system" |
| 14 | 13 |
"github.com/moby/moby/client" |
| 15 | 14 |
"github.com/moby/moby/v2/internal/testutil/fixtures/load" |
| ... | ... |
@@ -20,11 +19,11 @@ import ( |
| 20 | 20 |
// Execution contains information about the current test execution and daemon |
| 21 | 21 |
// under test |
| 22 | 22 |
type Execution struct {
|
| 23 |
- client client.APIClient |
|
| 24 |
- DaemonInfo system.Info |
|
| 25 |
- DaemonVersion types.Version |
|
| 26 |
- PlatformDefaults PlatformDefaults |
|
| 27 |
- protectedElements protectedElements |
|
| 23 |
+ client client.APIClient |
|
| 24 |
+ DaemonInfo system.Info |
|
| 25 |
+ DaemonMinAPIVersion string |
|
| 26 |
+ PlatformDefaults PlatformDefaults |
|
| 27 |
+ protectedElements protectedElements |
|
| 28 | 28 |
} |
| 29 | 29 |
|
| 30 | 30 |
// PlatformDefaults are defaults values for the platform of the daemon under test |
| ... | ... |
@@ -46,22 +45,27 @@ func New(ctx context.Context) (*Execution, error) {
|
| 46 | 46 |
|
| 47 | 47 |
// FromClient creates a new Execution environment from the passed in client |
| 48 | 48 |
func FromClient(ctx context.Context, c *client.Client) (*Execution, error) {
|
| 49 |
+ _, err := c.Ping(ctx, client.PingOptions{NegotiateAPIVersion: true})
|
|
| 50 |
+ if err != nil {
|
|
| 51 |
+ return nil, errors.Wrapf(err, "failed to ping daemon to negotiate api version") |
|
| 52 |
+ } |
|
| 53 |
+ |
|
| 49 | 54 |
result, err := c.Info(ctx, client.InfoOptions{})
|
| 50 | 55 |
if err != nil {
|
| 51 | 56 |
return nil, errors.Wrapf(err, "failed to get info from daemon") |
| 52 | 57 |
} |
| 53 |
- info := result.Info |
|
| 54 |
- v, err := c.ServerVersion(context.Background()) |
|
| 58 |
+ |
|
| 59 |
+ version, err := c.ServerVersion(ctx, client.ServerVersionOptions{})
|
|
| 55 | 60 |
if err != nil {
|
| 56 |
- return nil, errors.Wrapf(err, "failed to get version info from daemon") |
|
| 61 |
+ return nil, errors.Wrapf(err, "failed to get version from daemon") |
|
| 57 | 62 |
} |
| 58 | 63 |
|
| 59 | 64 |
return &Execution{
|
| 60 |
- client: c, |
|
| 61 |
- DaemonInfo: info, |
|
| 62 |
- DaemonVersion: v, |
|
| 63 |
- PlatformDefaults: getPlatformDefaults(info), |
|
| 64 |
- protectedElements: newProtectedElements(), |
|
| 65 |
+ client: c, |
|
| 66 |
+ DaemonInfo: result.Info, |
|
| 67 |
+ DaemonMinAPIVersion: version.MinAPIVersion, |
|
| 68 |
+ PlatformDefaults: getPlatformDefaults(result.Info), |
|
| 69 |
+ protectedElements: newProtectedElements(), |
|
| 65 | 70 |
}, nil |
| 66 | 71 |
} |
| 67 | 72 |
|
| ... | ... |
@@ -129,11 +133,7 @@ func (e *Execution) IsRemoteDaemon() bool {
|
| 129 | 129 |
|
| 130 | 130 |
// DaemonAPIVersion returns the negotiated daemon api version |
| 131 | 131 |
func (e *Execution) DaemonAPIVersion() string {
|
| 132 |
- version, err := e.APIClient().ServerVersion(context.TODO()) |
|
| 133 |
- if err != nil {
|
|
| 134 |
- return "" |
|
| 135 |
- } |
|
| 136 |
- return version.APIVersion |
|
| 132 |
+ return e.APIClient().ClientVersion() |
|
| 137 | 133 |
} |
| 138 | 134 |
|
| 139 | 135 |
// Print the execution details to stdout |
| ... | ... |
@@ -228,7 +228,7 @@ func (e *Execution) GitHubActions() bool {
|
| 228 | 228 |
|
| 229 | 229 |
// NotAmd64 returns true if the daemon's architecture is not amd64 |
| 230 | 230 |
func (e *Execution) NotAmd64() bool {
|
| 231 |
- return e.DaemonVersion.Arch != "amd64" |
|
| 231 |
+ return e.DaemonInfo.Architecture != "amd64" |
|
| 232 | 232 |
} |
| 233 | 233 |
|
| 234 | 234 |
// FirewallBackendDriver returns the value of FirewallBackend.Driver from |
| ... | ... |
@@ -5,7 +5,6 @@ import ( |
| 5 | 5 |
"io" |
| 6 | 6 |
"net" |
| 7 | 7 |
|
| 8 |
- "github.com/moby/moby/api/types" |
|
| 9 | 8 |
"github.com/moby/moby/api/types/network" |
| 10 | 9 |
"github.com/moby/moby/api/types/system" |
| 11 | 10 |
) |
| ... | ... |
@@ -27,7 +26,7 @@ type stableAPIClient interface {
|
| 27 | 27 |
VolumeAPIClient |
| 28 | 28 |
ClientVersion() string |
| 29 | 29 |
DaemonHost() string |
| 30 |
- ServerVersion(ctx context.Context) (types.Version, error) |
|
| 30 |
+ ServerVersion(ctx context.Context, options ServerVersionOptions) (ServerVersionResult, error) |
|
| 31 | 31 |
HijackDialer |
| 32 | 32 |
Dialer() func(context.Context) (net.Conn, error) |
| 33 | 33 |
Close() error |
| ... | ... |
@@ -7,15 +7,56 @@ import ( |
| 7 | 7 |
"github.com/moby/moby/api/types" |
| 8 | 8 |
) |
| 9 | 9 |
|
| 10 |
-// ServerVersion returns information of the docker client and server host. |
|
| 11 |
-func (cli *Client) ServerVersion(ctx context.Context) (types.Version, error) {
|
|
| 10 |
+// ServerVersionOptions specifies options for the server version request. |
|
| 11 |
+type ServerVersionOptions struct {
|
|
| 12 |
+ // Currently no options are supported. |
|
| 13 |
+} |
|
| 14 |
+ |
|
| 15 |
+// ServerVersionResult contains information about the Docker server host. |
|
| 16 |
+type ServerVersionResult struct {
|
|
| 17 |
+ // Platform is the platform (product name) the server is running on. |
|
| 18 |
+ Platform PlatformInfo |
|
| 19 |
+ |
|
| 20 |
+ // APIVersion is the highest API version supported by the server. |
|
| 21 |
+ APIVersion string |
|
| 22 |
+ |
|
| 23 |
+ // MinAPIVersion is the minimum API version the server supports. |
|
| 24 |
+ MinAPIVersion string |
|
| 25 |
+ |
|
| 26 |
+ // Components contains version information for the components making |
|
| 27 |
+ // up the server. Information in this field is for informational |
|
| 28 |
+ // purposes, and not part of the API contract. |
|
| 29 |
+ Components []types.ComponentVersion |
|
| 30 |
+} |
|
| 31 |
+ |
|
| 32 |
+// PlatformInfo holds information about the platform (product name) the |
|
| 33 |
+// server is running on. |
|
| 34 |
+type PlatformInfo struct {
|
|
| 35 |
+ // Name is the name of the platform (for example, "Docker Engine - Community", |
|
| 36 |
+ // or "Docker Desktop 4.49.0 (208003)") |
|
| 37 |
+ Name string |
|
| 38 |
+} |
|
| 39 |
+ |
|
| 40 |
+// ServerVersion returns information of the Docker server host. |
|
| 41 |
+func (cli *Client) ServerVersion(ctx context.Context, _ ServerVersionOptions) (ServerVersionResult, error) {
|
|
| 12 | 42 |
resp, err := cli.get(ctx, "/version", nil, nil) |
| 13 | 43 |
defer ensureReaderClosed(resp) |
| 14 | 44 |
if err != nil {
|
| 15 |
- return types.Version{}, err
|
|
| 45 |
+ return ServerVersionResult{}, err
|
|
| 46 |
+ } |
|
| 47 |
+ |
|
| 48 |
+ var v types.Version |
|
| 49 |
+ err = json.NewDecoder(resp.Body).Decode(&v) |
|
| 50 |
+ if err != nil {
|
|
| 51 |
+ return ServerVersionResult{}, err
|
|
| 16 | 52 |
} |
| 17 | 53 |
|
| 18 |
- var server types.Version |
|
| 19 |
- err = json.NewDecoder(resp.Body).Decode(&server) |
|
| 20 |
- return server, err |
|
| 54 |
+ return ServerVersionResult{
|
|
| 55 |
+ Platform: PlatformInfo{
|
|
| 56 |
+ Name: v.Platform.Name, |
|
| 57 |
+ }, |
|
| 58 |
+ APIVersion: v.APIVersion, |
|
| 59 |
+ MinAPIVersion: v.MinAPIVersion, |
|
| 60 |
+ Components: v.Components, |
|
| 61 |
+ }, nil |
|
| 21 | 62 |
} |