mirror of
https://github.com/moby/moby.git
synced 2026-01-11 10:41:43 +00:00
client: refactor Events, Info, RegistryLogin
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>
This commit is contained in:
committed by
Sebastiaan van Stijn
parent
c438b3fbbf
commit
e46058cbae
@@ -7,9 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/moby/moby/api/types"
|
"github.com/moby/moby/api/types"
|
||||||
"github.com/moby/moby/api/types/container"
|
"github.com/moby/moby/api/types/container"
|
||||||
"github.com/moby/moby/api/types/events"
|
|
||||||
"github.com/moby/moby/api/types/network"
|
"github.com/moby/moby/api/types/network"
|
||||||
"github.com/moby/moby/api/types/registry"
|
|
||||||
"github.com/moby/moby/api/types/system"
|
"github.com/moby/moby/api/types/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -176,9 +174,9 @@ type SwarmAPIClient interface {
|
|||||||
|
|
||||||
// SystemAPIClient defines API client methods for the system
|
// SystemAPIClient defines API client methods for the system
|
||||||
type SystemAPIClient interface {
|
type SystemAPIClient interface {
|
||||||
Events(ctx context.Context, options EventsListOptions) (<-chan events.Message, <-chan error)
|
Events(ctx context.Context, options EventsListOptions) EventsResult
|
||||||
Info(ctx context.Context) (system.Info, error)
|
Info(ctx context.Context, options InfoOptions) (SystemInfoResult, error)
|
||||||
RegistryLogin(ctx context.Context, auth registry.AuthConfig) (registry.AuthenticateOKBody, error)
|
RegistryLogin(ctx context.Context, auth RegistryLoginOptions) (RegistryLoginResult, error)
|
||||||
DiskUsage(ctx context.Context, options DiskUsageOptions) (system.DiskUsage, error)
|
DiskUsage(ctx context.Context, options DiskUsageOptions) (system.DiskUsage, error)
|
||||||
Ping(ctx context.Context, options PingOptions) (PingResult, error)
|
Ping(ctx context.Context, options PingOptions) (PingResult, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -408,13 +408,13 @@ func TestNegotiateAPIVersionAutomatic(t *testing.T) {
|
|||||||
// First request should trigger negotiation
|
// First request should trigger negotiation
|
||||||
pingVersion = "1.50"
|
pingVersion = "1.50"
|
||||||
expected = "1.50"
|
expected = "1.50"
|
||||||
_, _ = client.Info(ctx)
|
_, _ = client.Info(ctx, InfoOptions{})
|
||||||
assert.Check(t, is.Equal(client.ClientVersion(), expected))
|
assert.Check(t, is.Equal(client.ClientVersion(), expected))
|
||||||
|
|
||||||
// Once successfully negotiated, subsequent requests should not re-negotiate
|
// Once successfully negotiated, subsequent requests should not re-negotiate
|
||||||
pingVersion = "1.49"
|
pingVersion = "1.49"
|
||||||
expected = "1.50"
|
expected = "1.50"
|
||||||
_, _ = client.Info(ctx)
|
_, _ = client.Info(ctx, InfoOptions{})
|
||||||
assert.Check(t, is.Equal(client.ClientVersion(), expected))
|
assert.Check(t, is.Equal(client.ClientVersion(), expected))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,17 +8,38 @@ import (
|
|||||||
"github.com/moby/moby/api/types/registry"
|
"github.com/moby/moby/api/types/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type RegistryLoginOptions struct {
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
ServerAddress string
|
||||||
|
IdentityToken string
|
||||||
|
RegistryToken string
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegistryLoginResult holds the result of a RegistryLogin query.
|
||||||
|
type RegistryLoginResult struct {
|
||||||
|
Auth registry.AuthenticateOKBody
|
||||||
|
}
|
||||||
|
|
||||||
// RegistryLogin authenticates the docker server with a given docker registry.
|
// RegistryLogin authenticates the docker server with a given docker registry.
|
||||||
// It returns unauthorizedError when the authentication fails.
|
// It returns unauthorizedError when the authentication fails.
|
||||||
func (cli *Client) RegistryLogin(ctx context.Context, auth registry.AuthConfig) (registry.AuthenticateOKBody, error) {
|
func (cli *Client) RegistryLogin(ctx context.Context, options RegistryLoginOptions) (RegistryLoginResult, error) {
|
||||||
|
auth := registry.AuthConfig{
|
||||||
|
Username: options.Username,
|
||||||
|
Password: options.Password,
|
||||||
|
ServerAddress: options.ServerAddress,
|
||||||
|
IdentityToken: options.IdentityToken,
|
||||||
|
RegistryToken: options.RegistryToken,
|
||||||
|
}
|
||||||
|
|
||||||
resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil)
|
resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil)
|
||||||
defer ensureReaderClosed(resp)
|
defer ensureReaderClosed(resp)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return registry.AuthenticateOKBody{}, err
|
return RegistryLoginResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var response registry.AuthenticateOKBody
|
var response registry.AuthenticateOKBody
|
||||||
err = json.NewDecoder(resp.Body).Decode(&response)
|
err = json.NewDecoder(resp.Body).Decode(&response)
|
||||||
return response, err
|
return RegistryLoginResult{Auth: response}, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,17 @@ type EventsListOptions struct {
|
|||||||
Filters Filters
|
Filters Filters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EventsResult holds the result of an Events query.
|
||||||
|
type EventsResult struct {
|
||||||
|
Messages <-chan events.Message
|
||||||
|
Err <-chan error
|
||||||
|
}
|
||||||
|
|
||||||
// Events returns a stream of events in the daemon. It's up to the caller to close the stream
|
// Events returns a stream of events in the daemon. It's up to the caller to close the stream
|
||||||
// by cancelling the context. Once the stream has been completely read an [io.EOF] error is
|
// by cancelling the context. Once the stream has been completely read an [io.EOF] error is
|
||||||
// sent over the error channel. If an error is sent, all processing is stopped. It's up
|
// sent over the error channel. If an error is sent, all processing is stopped. It's up
|
||||||
// to the caller to reopen the stream in the event of an error by reinvoking this method.
|
// to the caller to reopen the stream in the event of an error by reinvoking this method.
|
||||||
func (cli *Client) Events(ctx context.Context, options EventsListOptions) (<-chan events.Message, <-chan error) {
|
func (cli *Client) Events(ctx context.Context, options EventsListOptions) EventsResult {
|
||||||
messages := make(chan events.Message)
|
messages := make(chan events.Message)
|
||||||
errs := make(chan error, 1)
|
errs := make(chan error, 1)
|
||||||
|
|
||||||
@@ -76,7 +82,10 @@ func (cli *Client) Events(ctx context.Context, options EventsListOptions) (<-cha
|
|||||||
}()
|
}()
|
||||||
<-started
|
<-started
|
||||||
|
|
||||||
return messages, errs
|
return EventsResult{
|
||||||
|
Messages: messages,
|
||||||
|
Err: errs,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildEventsQueryParams(options EventsListOptions) (url.Values, error) {
|
func buildEventsQueryParams(options EventsListOptions) (url.Values, error) {
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ func TestEventsErrorInOptions(t *testing.T) {
|
|||||||
for _, tc := range errorCases {
|
for _, tc := range errorCases {
|
||||||
client, err := NewClientWithOpts(WithMockClient(errorMock(http.StatusInternalServerError, "Server error")))
|
client, err := NewClientWithOpts(WithMockClient(errorMock(http.StatusInternalServerError, "Server error")))
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
_, errs := client.Events(context.Background(), tc.options)
|
events := client.Events(context.Background(), tc.options)
|
||||||
err = <-errs
|
err = <-events.Err
|
||||||
assert.Check(t, is.ErrorContains(err, tc.expectedError))
|
assert.Check(t, is.ErrorContains(err, tc.expectedError))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,8 +46,8 @@ func TestEventsErrorInOptions(t *testing.T) {
|
|||||||
func TestEventsErrorFromServer(t *testing.T) {
|
func TestEventsErrorFromServer(t *testing.T) {
|
||||||
client, err := NewClientWithOpts(WithMockClient(errorMock(http.StatusInternalServerError, "Server error")))
|
client, err := NewClientWithOpts(WithMockClient(errorMock(http.StatusInternalServerError, "Server error")))
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
_, errs := client.Events(context.Background(), EventsListOptions{})
|
events := client.Events(context.Background(), EventsListOptions{})
|
||||||
err = <-errs
|
err = <-events.Err
|
||||||
assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal))
|
assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,18 +133,18 @@ func TestEvents(t *testing.T) {
|
|||||||
}))
|
}))
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
messages, errs := client.Events(context.Background(), eventsCase.options)
|
events := client.Events(context.Background(), eventsCase.options)
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case err := <-errs:
|
case err := <-events.Err:
|
||||||
if err != nil && !errors.Is(err, io.EOF) {
|
if err != nil && !errors.Is(err, io.EOF) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
break loop
|
break loop
|
||||||
case e := <-messages:
|
case e := <-events.Messages:
|
||||||
_, ok := eventsCase.expectedEvents[e.Actor.ID]
|
_, ok := eventsCase.expectedEvents[e.Actor.ID]
|
||||||
assert.Check(t, ok, "event received not expected with action %s & id %s", e.Action, e.Actor.ID)
|
assert.Check(t, ok, "event received not expected with action %s & id %s", e.Action, e.Actor.ID)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,18 +9,26 @@ import (
|
|||||||
"github.com/moby/moby/api/types/system"
|
"github.com/moby/moby/api/types/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type InfoOptions struct {
|
||||||
|
// No options currently; placeholder for future use
|
||||||
|
}
|
||||||
|
|
||||||
|
type SystemInfoResult struct {
|
||||||
|
Info system.Info
|
||||||
|
}
|
||||||
|
|
||||||
// Info returns information about the docker server.
|
// Info returns information about the docker server.
|
||||||
func (cli *Client) Info(ctx context.Context) (system.Info, error) {
|
func (cli *Client) Info(ctx context.Context, options InfoOptions) (SystemInfoResult, error) {
|
||||||
var info system.Info
|
|
||||||
resp, err := cli.get(ctx, "/info", url.Values{}, nil)
|
resp, err := cli.get(ctx, "/info", url.Values{}, nil)
|
||||||
defer ensureReaderClosed(resp)
|
defer ensureReaderClosed(resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return info, err
|
return SystemInfoResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var info system.Info
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
|
if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
|
||||||
return info, fmt.Errorf("Error reading remote info: %v", err)
|
return SystemInfoResult{}, fmt.Errorf("Error reading remote info: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return info, nil
|
return SystemInfoResult{Info: info}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,14 +14,14 @@ import (
|
|||||||
func TestInfoServerError(t *testing.T) {
|
func TestInfoServerError(t *testing.T) {
|
||||||
client, err := NewClientWithOpts(WithMockClient(errorMock(http.StatusInternalServerError, "Server error")))
|
client, err := NewClientWithOpts(WithMockClient(errorMock(http.StatusInternalServerError, "Server error")))
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
_, err = client.Info(context.Background())
|
_, err = client.Info(context.Background(), InfoOptions{})
|
||||||
assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal))
|
assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInfoInvalidResponseJSONError(t *testing.T) {
|
func TestInfoInvalidResponseJSONError(t *testing.T) {
|
||||||
client, err := NewClientWithOpts(WithMockClient(mockResponse(http.StatusOK, nil, "invalid json")))
|
client, err := NewClientWithOpts(WithMockClient(mockResponse(http.StatusOK, nil, "invalid json")))
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
_, err = client.Info(context.Background())
|
_, err = client.Info(context.Background(), InfoOptions{})
|
||||||
assert.Check(t, is.ErrorContains(err, "invalid character"))
|
assert.Check(t, is.ErrorContains(err, "invalid character"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,8 +38,9 @@ func TestInfo(t *testing.T) {
|
|||||||
}))
|
}))
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
info, err := client.Info(context.Background())
|
result, err := client.Info(context.Background(), InfoOptions{})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
info := result.Info
|
||||||
|
|
||||||
assert.Check(t, is.Equal(info.ID, "daemonID"))
|
assert.Check(t, is.Equal(info.ID, "daemonID"))
|
||||||
assert.Check(t, is.Equal(info.Containers, 3))
|
assert.Check(t, is.Equal(info.Containers, 3))
|
||||||
@@ -68,8 +69,9 @@ func TestInfoWithDiscoveredDevices(t *testing.T) {
|
|||||||
}))
|
}))
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
info, err := client.Info(context.Background())
|
result, err := client.Info(context.Background(), InfoOptions{})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
info := result.Info
|
||||||
|
|
||||||
assert.Check(t, is.Equal(info.ID, "daemonID"))
|
assert.Check(t, is.Equal(info.ID, "daemonID"))
|
||||||
assert.Check(t, is.Equal(info.Containers, 3))
|
assert.Check(t, is.Equal(info.Containers, 3))
|
||||||
|
|||||||
@@ -756,9 +756,9 @@ func checkClusterHealth(t *testing.T, cl []*daemon.Daemon, managerCount, workerC
|
|||||||
|
|
||||||
// check info in a poll.WaitOn(), because if the cluster doesn't have a leader, `info` will return an error
|
// check info in a poll.WaitOn(), because if the cluster doesn't have a leader, `info` will return an error
|
||||||
checkInfo := func(t *testing.T) (any, string) {
|
checkInfo := func(t *testing.T) (any, string) {
|
||||||
client := d.NewClientT(t)
|
apiClient := d.NewClientT(t)
|
||||||
daemonInfo, err := client.Info(ctx)
|
result, err := apiClient.Info(ctx, client.InfoOptions{})
|
||||||
info = daemonInfo.Swarm
|
info = result.Info.Swarm
|
||||||
return err, "cluster not ready in time"
|
return err, "cluster not ready in time"
|
||||||
}
|
}
|
||||||
poll.WaitOn(t, pollCheck(t, checkInfo, checker.IsNil()), poll.WithTimeout(defaultReconciliationTimeout))
|
poll.WaitOn(t, pollCheck(t, checkInfo, checker.IsNil()), poll.WithTimeout(defaultReconciliationTimeout))
|
||||||
|
|||||||
@@ -21,8 +21,9 @@ func (s *DockerCLIInfoSuite) TestInfoSecurityOptions(c *testing.T) {
|
|||||||
apiClient, err := client.NewClientWithOpts(client.FromEnv)
|
apiClient, err := client.NewClientWithOpts(client.FromEnv)
|
||||||
assert.NilError(c, err)
|
assert.NilError(c, err)
|
||||||
defer apiClient.Close()
|
defer apiClient.Close()
|
||||||
info, err := apiClient.Info(testutil.GetContext(c))
|
result, err := apiClient.Info(testutil.GetContext(c), client.InfoOptions{})
|
||||||
assert.NilError(c, err)
|
assert.NilError(c, err)
|
||||||
|
info := result.Info
|
||||||
|
|
||||||
if Apparmor() {
|
if Apparmor() {
|
||||||
assert.Check(c, is.Contains(info.SecurityOptions, "name=apparmor"))
|
assert.Check(c, is.Contains(info.SecurityOptions, "name=apparmor"))
|
||||||
|
|||||||
@@ -54,8 +54,9 @@ func (s *DockerCLIPluginLogDriverSuite) TestPluginLogDriverInfoList(c *testing.T
|
|||||||
assert.NilError(c, err)
|
assert.NilError(c, err)
|
||||||
defer apiClient.Close()
|
defer apiClient.Close()
|
||||||
|
|
||||||
info, err := apiClient.Info(testutil.GetContext(c))
|
result, err := apiClient.Info(testutil.GetContext(c), client.InfoOptions{})
|
||||||
assert.NilError(c, err)
|
assert.NilError(c, err)
|
||||||
|
info := result.Info
|
||||||
|
|
||||||
drivers := strings.Join(info.Plugins.Log, " ")
|
drivers := strings.Join(info.Plugins.Log, " ")
|
||||||
assert.Assert(c, is.Contains(drivers, "json-file"))
|
assert.Assert(c, is.Contains(drivers, "json-file"))
|
||||||
|
|||||||
@@ -200,8 +200,9 @@ func daemonTime(t *testing.T) time.Time {
|
|||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
defer apiClient.Close()
|
defer apiClient.Close()
|
||||||
|
|
||||||
info, err := apiClient.Info(testutil.GetContext(t))
|
result, err := apiClient.Info(testutil.GetContext(t), client.InfoOptions{})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
info := result.Info
|
||||||
|
|
||||||
dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
|
dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
|
||||||
assert.Assert(t, err == nil, "invalid time format in GET /info response")
|
assert.Assert(t, err == nil, "invalid time format in GET /info response")
|
||||||
@@ -286,11 +287,11 @@ func minimalBaseImage() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getGoroutineNumber(ctx context.Context, apiClient client.APIClient) (int, error) {
|
func getGoroutineNumber(ctx context.Context, apiClient client.APIClient) (int, error) {
|
||||||
info, err := apiClient.Info(ctx)
|
result, err := apiClient.Info(ctx, client.InfoOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return info.NGoroutines, nil
|
return result.Info.NGoroutines, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitForStableGoroutineCount(ctx context.Context, t poll.TestingT, apiClient client.APIClient) int {
|
func waitForStableGoroutineCount(ctx context.Context, t poll.TestingT, apiClient client.APIClient) int {
|
||||||
|
|||||||
@@ -740,10 +740,12 @@ func TestBuildEmitsImageCreateEvent(t *testing.T) {
|
|||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
buildLogs := out.String()
|
buildLogs := out.String()
|
||||||
|
|
||||||
eventsChan, errs := apiClient.Events(ctx, client.EventsListOptions{
|
result := apiClient.Events(ctx, client.EventsListOptions{
|
||||||
Since: since.Format(time.RFC3339Nano),
|
Since: since.Format(time.RFC3339Nano),
|
||||||
Until: time.Now().Format(time.RFC3339Nano),
|
Until: time.Now().Format(time.RFC3339Nano),
|
||||||
})
|
})
|
||||||
|
eventsChan := result.Messages
|
||||||
|
errs := result.Err
|
||||||
|
|
||||||
var eventsReceived []string
|
var eventsReceived []string
|
||||||
imageCreateEvts := 0
|
imageCreateEvts := 0
|
||||||
|
|||||||
@@ -188,8 +188,9 @@ func TestCDIInfoDiscoveredDevices(t *testing.T) {
|
|||||||
defer d.Stop(t)
|
defer d.Stop(t)
|
||||||
|
|
||||||
c := d.NewClientT(t)
|
c := d.NewClientT(t)
|
||||||
info, err := c.Info(ctx)
|
result, err := c.Info(ctx, client.InfoOptions{})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
info := result.Info
|
||||||
|
|
||||||
assert.Check(t, is.Len(info.CDISpecDirs, 1))
|
assert.Check(t, is.Len(info.CDISpecDirs, 1))
|
||||||
assert.Check(t, is.Equal(info.CDISpecDirs[0], cdiDir))
|
assert.Check(t, is.Equal(info.CDISpecDirs[0], cdiDir))
|
||||||
|
|||||||
@@ -807,9 +807,10 @@ func TestContainerdContainerImageInfo(t *testing.T) {
|
|||||||
apiClient := testEnv.APIClient()
|
apiClient := testEnv.APIClient()
|
||||||
defer apiClient.Close()
|
defer apiClient.Close()
|
||||||
|
|
||||||
info, err := apiClient.Info(ctx)
|
result, err := apiClient.Info(ctx, client.InfoOptions{})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
info := result.Info
|
||||||
skip.If(t, info.Containerd == nil, "requires containerd")
|
skip.If(t, info.Containerd == nil, "requires containerd")
|
||||||
|
|
||||||
// Currently a containerd container is only created when the container is started.
|
// Currently a containerd container is only created when the container is started.
|
||||||
|
|||||||
@@ -98,10 +98,11 @@ func TestMountDaemonRoot(t *testing.T) {
|
|||||||
|
|
||||||
ctx := setupTest(t)
|
ctx := setupTest(t)
|
||||||
apiClient := testEnv.APIClient()
|
apiClient := testEnv.APIClient()
|
||||||
info, err := apiClient.Info(ctx)
|
result, err := apiClient.Info(ctx, client.InfoOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
info := result.Info
|
||||||
|
|
||||||
for _, test := range []struct {
|
for _, test := range []struct {
|
||||||
desc string
|
desc string
|
||||||
|
|||||||
@@ -39,11 +39,13 @@ func TestPause(t *testing.T) {
|
|||||||
|
|
||||||
until := request.DaemonUnixTime(ctx, t, apiClient, testEnv)
|
until := request.DaemonUnixTime(ctx, t, apiClient, testEnv)
|
||||||
|
|
||||||
messages, errs := apiClient.Events(ctx, client.EventsListOptions{
|
result := apiClient.Events(ctx, client.EventsListOptions{
|
||||||
Since: since,
|
Since: since,
|
||||||
Until: until,
|
Until: until,
|
||||||
Filters: make(client.Filters).Add(string(events.ContainerEventType), cID),
|
Filters: make(client.Filters).Add(string(events.ContainerEventType), cID),
|
||||||
})
|
})
|
||||||
|
messages := result.Messages
|
||||||
|
errs := result.Err
|
||||||
assert.Check(t, is.DeepEqual([]events.Action{events.ActionPause, events.ActionUnPause}, getEventActions(t, messages, errs)))
|
assert.Check(t, is.DeepEqual([]events.Action{events.ActionPause, events.ActionUnPause}, getEventActions(t, messages, errs)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -247,9 +247,11 @@ func TestContainerRestartWithCancelledRequest(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// Start listening for events.
|
// Start listening for events.
|
||||||
messages, errs := apiClient.Events(ctx, client.EventsListOptions{
|
result := apiClient.Events(ctx, client.EventsListOptions{
|
||||||
Filters: make(client.Filters).Add("container", cID).Add("event", string(events.ActionRestart)),
|
Filters: make(client.Filters).Add("container", cID).Add("event", string(events.ActionRestart)),
|
||||||
})
|
})
|
||||||
|
messages := result.Messages
|
||||||
|
errs := result.Err
|
||||||
|
|
||||||
// Make restart request, but cancel the request before the container
|
// Make restart request, but cancel the request before the container
|
||||||
// is (forcibly) killed.
|
// is (forcibly) killed.
|
||||||
|
|||||||
@@ -21,9 +21,10 @@ func TestStats(t *testing.T) {
|
|||||||
ctx := setupTest(t)
|
ctx := setupTest(t)
|
||||||
apiClient := testEnv.APIClient()
|
apiClient := testEnv.APIClient()
|
||||||
|
|
||||||
info, err := apiClient.Info(ctx)
|
result, err := apiClient.Info(ctx, client.InfoOptions{})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
info := result.Info
|
||||||
cID := container.Run(ctx, t, apiClient)
|
cID := container.Run(ctx, t, apiClient)
|
||||||
t.Run("no-stream", func(t *testing.T) {
|
t.Run("no-stream", func(t *testing.T) {
|
||||||
resp, err := apiClient.ContainerStats(ctx, cID, client.ContainerStatsOptions{
|
resp, err := apiClient.ContainerStats(ctx, cID, client.ContainerStatsOptions{
|
||||||
|
|||||||
@@ -70,9 +70,9 @@ func CheckGoroutineCount(ctx context.Context, apiClient client.SystemAPIClient,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getGoroutineNumber(ctx context.Context, apiClient client.SystemAPIClient) (int, error) {
|
func getGoroutineNumber(ctx context.Context, apiClient client.SystemAPIClient) (int, error) {
|
||||||
info, err := apiClient.Info(ctx)
|
result, err := apiClient.Info(ctx, client.InfoOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return info.NGoroutines, nil
|
return result.Info.NGoroutines, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,8 +31,9 @@ func TestInfoFirewallBackend(t *testing.T) {
|
|||||||
if !testEnv.IsRootless() && networking.FirewalldRunning() {
|
if !testEnv.IsRootless() && networking.FirewalldRunning() {
|
||||||
expDriver += "+firewalld"
|
expDriver += "+firewalld"
|
||||||
}
|
}
|
||||||
info, err := c.Info(ctx)
|
result, err := c.Info(ctx, client.InfoOptions{})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
info := result.Info
|
||||||
assert.Assert(t, info.FirewallBackend != nil, "expected firewall backend in info response")
|
assert.Assert(t, info.FirewallBackend != nil, "expected firewall backend in info response")
|
||||||
t.Log("FirewallBackend: Driver:", info.FirewallBackend.Driver)
|
t.Log("FirewallBackend: Driver:", info.FirewallBackend.Driver)
|
||||||
for _, kv := range info.FirewallBackend.Info {
|
for _, kv := range info.FirewallBackend.Info {
|
||||||
@@ -43,8 +44,9 @@ func TestInfoFirewallBackend(t *testing.T) {
|
|||||||
// Check FirewallBackend is omitted for API <= 1.48.
|
// Check FirewallBackend is omitted for API <= 1.48.
|
||||||
t.Run("api 1.48", func(t *testing.T) {
|
t.Run("api 1.48", func(t *testing.T) {
|
||||||
c148 := request.NewAPIClient(t, client.WithVersion("1.48"))
|
c148 := request.NewAPIClient(t, client.WithVersion("1.48"))
|
||||||
info148, err := c148.Info(ctx)
|
result, err := c148.Info(ctx, client.InfoOptions{})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
info148 := result.Info
|
||||||
assert.Check(t, is.Nil(info148.FirewallBackend))
|
assert.Check(t, is.Nil(info148.FirewallBackend))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -276,9 +276,10 @@ func systemTime(ctx context.Context, t *testing.T, apiClient client.APIClient, t
|
|||||||
return time.Now()
|
return time.Now()
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := apiClient.Info(ctx)
|
result, err := apiClient.Info(ctx, client.InfoOptions{})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
info := result.Info
|
||||||
dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
|
dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
|
||||||
assert.NilError(t, err, "invalid time format in GET /info response")
|
assert.NilError(t, err, "invalid time format in GET /info response")
|
||||||
return dt
|
return dt
|
||||||
@@ -289,9 +290,9 @@ func systemEventsSince(ctx context.Context, apiClient client.APIClient, since st
|
|||||||
Since: since,
|
Since: since,
|
||||||
}
|
}
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
events, errs := apiClient.Events(ctx, eventOptions)
|
result := apiClient.Events(ctx, eventOptions)
|
||||||
|
|
||||||
return events, errs, cancel
|
return result.Messages, result.Err, cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAuthZPluginErrorResponse(t *testing.T) {
|
func TestAuthZPluginErrorResponse(t *testing.T) {
|
||||||
|
|||||||
@@ -30,9 +30,11 @@ func TestEventsExecDie(t *testing.T) {
|
|||||||
})
|
})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
msg, errs := apiClient.Events(ctx, client.EventsListOptions{
|
result := apiClient.Events(ctx, client.EventsListOptions{
|
||||||
Filters: make(client.Filters).Add("container", cID).Add("event", string(events.ActionExecDie)),
|
Filters: make(client.Filters).Add("container", cID).Add("event", string(events.ActionExecDie)),
|
||||||
})
|
})
|
||||||
|
msg := result.Messages
|
||||||
|
errs := result.Err
|
||||||
|
|
||||||
_, err = apiClient.ExecStart(ctx, res.ID, client.ExecStartOptions{
|
_, err = apiClient.ExecStart(ctx, res.ID, client.ExecStartOptions{
|
||||||
Detach: true,
|
Detach: true,
|
||||||
@@ -107,11 +109,13 @@ func TestEventsVolumeCreate(t *testing.T) {
|
|||||||
Add("type", "volume").
|
Add("type", "volume").
|
||||||
Add("event", "create").
|
Add("event", "create").
|
||||||
Add("volume", volName)
|
Add("volume", volName)
|
||||||
messages, errs := apiClient.Events(ctx, client.EventsListOptions{
|
result := apiClient.Events(ctx, client.EventsListOptions{
|
||||||
Since: since,
|
Since: since,
|
||||||
Until: request.DaemonUnixTime(ctx, t, apiClient, testEnv),
|
Until: request.DaemonUnixTime(ctx, t, apiClient, testEnv),
|
||||||
Filters: filter,
|
Filters: filter,
|
||||||
})
|
})
|
||||||
|
messages := result.Messages
|
||||||
|
errs := result.Err
|
||||||
|
|
||||||
volEvents, err := getEvents(messages, errs)
|
volEvents, err := getEvents(messages, errs)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
@@ -123,11 +127,13 @@ func TestEventsVolumeCreate(t *testing.T) {
|
|||||||
Target: "/tmp/foo",
|
Target: "/tmp/foo",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
messages, errs = apiClient.Events(ctx, client.EventsListOptions{
|
result = apiClient.Events(ctx, client.EventsListOptions{
|
||||||
Since: since,
|
Since: since,
|
||||||
Until: request.DaemonUnixTime(ctx, t, apiClient, testEnv),
|
Until: request.DaemonUnixTime(ctx, t, apiClient, testEnv),
|
||||||
Filters: filter,
|
Filters: filter,
|
||||||
})
|
})
|
||||||
|
messages = result.Messages
|
||||||
|
errs = result.Err
|
||||||
|
|
||||||
volEvents, err = getEvents(messages, errs)
|
volEvents, err = getEvents(messages, errs)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/moby/moby/api/types/registry"
|
"github.com/moby/moby/api/types/registry"
|
||||||
|
"github.com/moby/moby/client"
|
||||||
"github.com/moby/moby/v2/internal/testutil"
|
"github.com/moby/moby/v2/internal/testutil"
|
||||||
"github.com/moby/moby/v2/internal/testutil/daemon"
|
"github.com/moby/moby/v2/internal/testutil/daemon"
|
||||||
"gotest.tools/v3/assert"
|
"gotest.tools/v3/assert"
|
||||||
@@ -17,9 +18,10 @@ func TestInfoAPI(t *testing.T) {
|
|||||||
ctx := setupTest(t)
|
ctx := setupTest(t)
|
||||||
apiClient := testEnv.APIClient()
|
apiClient := testEnv.APIClient()
|
||||||
|
|
||||||
info, err := apiClient.Info(ctx)
|
result, err := apiClient.Info(ctx, client.InfoOptions{})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
info := result.Info
|
||||||
// TODO(thaJeztah): make sure we have other tests that run a local daemon and check other fields based on known state.
|
// TODO(thaJeztah): make sure we have other tests that run a local daemon and check other fields based on known state.
|
||||||
assert.Check(t, info.ID != "")
|
assert.Check(t, info.ID != "")
|
||||||
assert.Check(t, is.Equal(info.Containers, info.ContainersRunning+info.ContainersPaused+info.ContainersStopped))
|
assert.Check(t, is.Equal(info.Containers, info.ContainersRunning+info.ContainersPaused+info.ContainersStopped))
|
||||||
@@ -51,9 +53,11 @@ func TestInfoAPIWarnings(t *testing.T) {
|
|||||||
d.Start(t, "-H=0.0.0.0:23756", "-H="+d.Sock())
|
d.Start(t, "-H=0.0.0.0:23756", "-H="+d.Sock())
|
||||||
defer d.Stop(t)
|
defer d.Stop(t)
|
||||||
|
|
||||||
info, err := c.Info(ctx)
|
result, err := c.Info(ctx, client.InfoOptions{})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
info := result.Info
|
||||||
|
|
||||||
stringsToCheck := []string{
|
stringsToCheck := []string{
|
||||||
"Access to the remote API is equivalent to root access",
|
"Access to the remote API is equivalent to root access",
|
||||||
"http://0.0.0.0:23756",
|
"http://0.0.0.0:23756",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/moby/moby/api/types/registry"
|
"github.com/moby/moby/client"
|
||||||
registrypkg "github.com/moby/moby/v2/daemon/pkg/registry"
|
registrypkg "github.com/moby/moby/v2/daemon/pkg/registry"
|
||||||
"github.com/moby/moby/v2/integration/internal/requirement"
|
"github.com/moby/moby/v2/integration/internal/requirement"
|
||||||
"gotest.tools/v3/assert"
|
"gotest.tools/v3/assert"
|
||||||
@@ -19,7 +19,7 @@ func TestLoginFailsWithBadCredentials(t *testing.T) {
|
|||||||
ctx := setupTest(t)
|
ctx := setupTest(t)
|
||||||
apiClient := testEnv.APIClient()
|
apiClient := testEnv.APIClient()
|
||||||
|
|
||||||
_, err := apiClient.RegistryLogin(ctx, registry.AuthConfig{
|
_, err := apiClient.RegistryLogin(ctx, client.RegistryLoginOptions{
|
||||||
Username: "no-user",
|
Username: "no-user",
|
||||||
Password: "no-password",
|
Password: "no-password",
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -985,8 +985,9 @@ func (d *Daemon) queryRootDir() (string, error) {
|
|||||||
func (d *Daemon) Info(t testing.TB) system.Info {
|
func (d *Daemon) Info(t testing.TB) system.Info {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
c := d.NewClientT(t)
|
c := d.NewClientT(t)
|
||||||
info, err := c.Info(context.Background())
|
result, err := c.Info(context.Background(), client.InfoOptions{})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
info := result.Info
|
||||||
assert.NilError(t, c.Close())
|
assert.NilError(t, c.Close())
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,8 +162,9 @@ func (d *Daemon) SwarmLeave(ctx context.Context, t testing.TB, force bool) error
|
|||||||
func (d *Daemon) SwarmInfo(ctx context.Context, t testing.TB) swarm.Info {
|
func (d *Daemon) SwarmInfo(ctx context.Context, t testing.TB) swarm.Info {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
cli := d.NewClientT(t)
|
cli := d.NewClientT(t)
|
||||||
info, err := cli.Info(ctx)
|
result, err := cli.Info(ctx, client.InfoOptions{})
|
||||||
assert.NilError(t, err, "get swarm info")
|
assert.NilError(t, err, "get swarm info")
|
||||||
|
info := result.Info
|
||||||
return info.Swarm
|
return info.Swarm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,10 +46,11 @@ func New(ctx context.Context) (*Execution, error) {
|
|||||||
|
|
||||||
// FromClient creates a new Execution environment from the passed in client
|
// FromClient creates a new Execution environment from the passed in client
|
||||||
func FromClient(ctx context.Context, c *client.Client) (*Execution, error) {
|
func FromClient(ctx context.Context, c *client.Client) (*Execution, error) {
|
||||||
info, err := c.Info(ctx)
|
result, err := c.Info(ctx, client.InfoOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to get info from daemon")
|
return nil, errors.Wrapf(err, "failed to get info from daemon")
|
||||||
}
|
}
|
||||||
|
info := result.Info
|
||||||
v, err := c.ServerVersion(context.Background())
|
v, err := c.ServerVersion(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to get version info from daemon")
|
return nil, errors.Wrapf(err, "failed to get version info from daemon")
|
||||||
|
|||||||
@@ -33,14 +33,15 @@ func NewAPIClient(t testing.TB, ops ...client.Opt) client.APIClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DaemonTime provides the current time on the daemon host
|
// DaemonTime provides the current time on the daemon host
|
||||||
func DaemonTime(ctx context.Context, t testing.TB, client client.APIClient, testEnv *environment.Execution) time.Time {
|
func DaemonTime(ctx context.Context, t testing.TB, apiClient client.APIClient, testEnv *environment.Execution) time.Time {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if testEnv.IsLocalDaemon() {
|
if testEnv.IsLocalDaemon() {
|
||||||
return time.Now()
|
return time.Now()
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := client.Info(ctx)
|
result, err := apiClient.Info(ctx, client.InfoOptions{})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
info := result.Info
|
||||||
|
|
||||||
dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
|
dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
|
||||||
assert.NilError(t, err, "invalid time format in GET /info response")
|
assert.NilError(t, err, "invalid time format in GET /info response")
|
||||||
|
|||||||
8
vendor/github.com/moby/moby/client/client_interfaces.go
generated
vendored
8
vendor/github.com/moby/moby/client/client_interfaces.go
generated
vendored
@@ -7,9 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/moby/moby/api/types"
|
"github.com/moby/moby/api/types"
|
||||||
"github.com/moby/moby/api/types/container"
|
"github.com/moby/moby/api/types/container"
|
||||||
"github.com/moby/moby/api/types/events"
|
|
||||||
"github.com/moby/moby/api/types/network"
|
"github.com/moby/moby/api/types/network"
|
||||||
"github.com/moby/moby/api/types/registry"
|
|
||||||
"github.com/moby/moby/api/types/system"
|
"github.com/moby/moby/api/types/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -176,9 +174,9 @@ type SwarmAPIClient interface {
|
|||||||
|
|
||||||
// SystemAPIClient defines API client methods for the system
|
// SystemAPIClient defines API client methods for the system
|
||||||
type SystemAPIClient interface {
|
type SystemAPIClient interface {
|
||||||
Events(ctx context.Context, options EventsListOptions) (<-chan events.Message, <-chan error)
|
Events(ctx context.Context, options EventsListOptions) EventsResult
|
||||||
Info(ctx context.Context) (system.Info, error)
|
Info(ctx context.Context, options InfoOptions) (SystemInfoResult, error)
|
||||||
RegistryLogin(ctx context.Context, auth registry.AuthConfig) (registry.AuthenticateOKBody, error)
|
RegistryLogin(ctx context.Context, auth RegistryLoginOptions) (RegistryLoginResult, error)
|
||||||
DiskUsage(ctx context.Context, options DiskUsageOptions) (system.DiskUsage, error)
|
DiskUsage(ctx context.Context, options DiskUsageOptions) (system.DiskUsage, error)
|
||||||
Ping(ctx context.Context, options PingOptions) (PingResult, error)
|
Ping(ctx context.Context, options PingOptions) (PingResult, error)
|
||||||
}
|
}
|
||||||
|
|||||||
27
vendor/github.com/moby/moby/client/login.go
generated
vendored
27
vendor/github.com/moby/moby/client/login.go
generated
vendored
@@ -8,17 +8,38 @@ import (
|
|||||||
"github.com/moby/moby/api/types/registry"
|
"github.com/moby/moby/api/types/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type RegistryLoginOptions struct {
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
ServerAddress string
|
||||||
|
IdentityToken string
|
||||||
|
RegistryToken string
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegistryLoginResult holds the result of a RegistryLogin query.
|
||||||
|
type RegistryLoginResult struct {
|
||||||
|
Auth registry.AuthenticateOKBody
|
||||||
|
}
|
||||||
|
|
||||||
// RegistryLogin authenticates the docker server with a given docker registry.
|
// RegistryLogin authenticates the docker server with a given docker registry.
|
||||||
// It returns unauthorizedError when the authentication fails.
|
// It returns unauthorizedError when the authentication fails.
|
||||||
func (cli *Client) RegistryLogin(ctx context.Context, auth registry.AuthConfig) (registry.AuthenticateOKBody, error) {
|
func (cli *Client) RegistryLogin(ctx context.Context, options RegistryLoginOptions) (RegistryLoginResult, error) {
|
||||||
|
auth := registry.AuthConfig{
|
||||||
|
Username: options.Username,
|
||||||
|
Password: options.Password,
|
||||||
|
ServerAddress: options.ServerAddress,
|
||||||
|
IdentityToken: options.IdentityToken,
|
||||||
|
RegistryToken: options.RegistryToken,
|
||||||
|
}
|
||||||
|
|
||||||
resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil)
|
resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil)
|
||||||
defer ensureReaderClosed(resp)
|
defer ensureReaderClosed(resp)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return registry.AuthenticateOKBody{}, err
|
return RegistryLoginResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var response registry.AuthenticateOKBody
|
var response registry.AuthenticateOKBody
|
||||||
err = json.NewDecoder(resp.Body).Decode(&response)
|
err = json.NewDecoder(resp.Body).Decode(&response)
|
||||||
return response, err
|
return RegistryLoginResult{Auth: response}, err
|
||||||
}
|
}
|
||||||
|
|||||||
13
vendor/github.com/moby/moby/client/system_events.go
generated
vendored
13
vendor/github.com/moby/moby/client/system_events.go
generated
vendored
@@ -19,11 +19,17 @@ type EventsListOptions struct {
|
|||||||
Filters Filters
|
Filters Filters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EventsResult holds the result of an Events query.
|
||||||
|
type EventsResult struct {
|
||||||
|
Messages <-chan events.Message
|
||||||
|
Err <-chan error
|
||||||
|
}
|
||||||
|
|
||||||
// Events returns a stream of events in the daemon. It's up to the caller to close the stream
|
// Events returns a stream of events in the daemon. It's up to the caller to close the stream
|
||||||
// by cancelling the context. Once the stream has been completely read an [io.EOF] error is
|
// by cancelling the context. Once the stream has been completely read an [io.EOF] error is
|
||||||
// sent over the error channel. If an error is sent, all processing is stopped. It's up
|
// sent over the error channel. If an error is sent, all processing is stopped. It's up
|
||||||
// to the caller to reopen the stream in the event of an error by reinvoking this method.
|
// to the caller to reopen the stream in the event of an error by reinvoking this method.
|
||||||
func (cli *Client) Events(ctx context.Context, options EventsListOptions) (<-chan events.Message, <-chan error) {
|
func (cli *Client) Events(ctx context.Context, options EventsListOptions) EventsResult {
|
||||||
messages := make(chan events.Message)
|
messages := make(chan events.Message)
|
||||||
errs := make(chan error, 1)
|
errs := make(chan error, 1)
|
||||||
|
|
||||||
@@ -76,7 +82,10 @@ func (cli *Client) Events(ctx context.Context, options EventsListOptions) (<-cha
|
|||||||
}()
|
}()
|
||||||
<-started
|
<-started
|
||||||
|
|
||||||
return messages, errs
|
return EventsResult{
|
||||||
|
Messages: messages,
|
||||||
|
Err: errs,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildEventsQueryParams(options EventsListOptions) (url.Values, error) {
|
func buildEventsQueryParams(options EventsListOptions) (url.Values, error) {
|
||||||
|
|||||||
18
vendor/github.com/moby/moby/client/system_info.go
generated
vendored
18
vendor/github.com/moby/moby/client/system_info.go
generated
vendored
@@ -9,18 +9,26 @@ import (
|
|||||||
"github.com/moby/moby/api/types/system"
|
"github.com/moby/moby/api/types/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type InfoOptions struct {
|
||||||
|
// No options currently; placeholder for future use
|
||||||
|
}
|
||||||
|
|
||||||
|
type SystemInfoResult struct {
|
||||||
|
Info system.Info
|
||||||
|
}
|
||||||
|
|
||||||
// Info returns information about the docker server.
|
// Info returns information about the docker server.
|
||||||
func (cli *Client) Info(ctx context.Context) (system.Info, error) {
|
func (cli *Client) Info(ctx context.Context, options InfoOptions) (SystemInfoResult, error) {
|
||||||
var info system.Info
|
|
||||||
resp, err := cli.get(ctx, "/info", url.Values{}, nil)
|
resp, err := cli.get(ctx, "/info", url.Values{}, nil)
|
||||||
defer ensureReaderClosed(resp)
|
defer ensureReaderClosed(resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return info, err
|
return SystemInfoResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var info system.Info
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
|
if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
|
||||||
return info, fmt.Errorf("Error reading remote info: %v", err)
|
return SystemInfoResult{}, fmt.Errorf("Error reading remote info: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return info, nil
|
return SystemInfoResult{Info: info}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user