Compare commits

...

13 Commits

Author SHA1 Message Date
Laura Brehm 0d482e4e4b
Merge 508337b62e into da9e984231 2024-10-18 10:43:46 +01:00
Sebastiaan van Stijn da9e984231
Merge pull request #5541 from thaJeztah/template_coverage
templates: add test for HeaderFunctions
2024-10-18 11:42:00 +02:00
Paweł Gronowski 38653277af
Merge pull request #5539 from thaJeztah/bump_swarmkit
vendor: github.com/moby/swarmkit/v2 v2.0.0-20241017191044-e8ecf83ee08e
2024-10-18 10:44:41 +02:00
Sebastiaan van Stijn 12dcc6e25c
templates: add test for HeaderFunctions
Before:

    go test -test.coverprofile -
    PASS
    coverage: 65.2% of statements
    ok  	github.com/docker/cli/templates	0.607s

After:

    go test -test.coverprofile -
    PASS
    coverage: 95.7% of statements
    ok  	github.com/docker/cli/templates	0.259s

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-10-18 10:07:33 +02:00
Sebastiaan van Stijn cbbb917323
vendor: github.com/moby/swarmkit/v2 v2.0.0-20241017191044-e8ecf83ee08e
- add Unwrap error to custom error types
- removes dependency on github.com/rexray/gocsi
- fix CSI plugin load issue

full diff: ea1a7cec35...e8ecf83ee0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-10-17 23:01:19 +02:00
Paweł Gronowski 3590f946a3
Merge pull request #5535 from dvdksn/fix-image-tag-spec
docs: update prose about image tag/name format
2024-10-17 12:46:46 +02:00
David Karlsson 2c6b80491b docs: update prose about image tag/name format
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
2024-10-17 12:36:32 +02:00
Paweł Gronowski 09e16fc9c6
Merge pull request #5537 from dvdksn/correct_events_limit
docs: corrected the max events returned
2024-10-17 11:26:09 +02:00
Laura Brehm dba4b15d6b
Merge pull request #5534 from thaJeztah/container_testfixes 2024-10-16 22:08:22 +01:00
David Karlsson 50ef0c58c2 docs: corrected the max events returned
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
2024-10-16 12:21:51 +02:00
Sebastiaan van Stijn 35d7b1a7a6
cli/command/container: TestWaitExitOrRemoved use subtests
=== RUN   TestWaitExitOrRemoved
    === RUN   TestWaitExitOrRemoved/normal-container
    === RUN   TestWaitExitOrRemoved/give-me-exit-code-42
    === RUN   TestWaitExitOrRemoved/i-want-a-wait-error
    time="2024-10-13T18:48:14+02:00" level=error msg="Error waiting for container: removal failed"
    === RUN   TestWaitExitOrRemoved/non-existent-container-id
    time="2024-10-13T18:48:14+02:00" level=error msg="error waiting for container: no such container: non-existent-container-id"
    --- PASS: TestWaitExitOrRemoved (0.00s)
        --- PASS: TestWaitExitOrRemoved/normal-container (0.00s)
        --- PASS: TestWaitExitOrRemoved/give-me-exit-code-42 (0.00s)
        --- PASS: TestWaitExitOrRemoved/i-want-a-wait-error (0.00s)
        --- PASS: TestWaitExitOrRemoved/non-existent-container-id (0.00s)
    PASS

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-10-16 12:03:17 +02:00
Sebastiaan van Stijn 3b38dc67be
cli/command/container: set empty args in tests and discard output
Prevent some tests from failing when running from a pre-compiled
testbinary, and discard output to make the output less noisy.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-10-16 12:01:25 +02:00
Laura Brehm 508337b62e
Replace deprecated usages of `assert.ErrorType`
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
2024-08-01 11:58:28 +01:00
18 changed files with 151 additions and 59 deletions

View File

@ -1,14 +1,13 @@
package manager package manager
import ( import (
"errors"
"fmt" "fmt"
"reflect"
"strings" "strings"
"testing" "testing"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
"gotest.tools/v3/assert/cmp"
) )
type fakeCandidate struct { type fakeCandidate struct {
@ -80,7 +79,8 @@ func TestValidateCandidate(t *testing.T) {
assert.ErrorContains(t, err, tc.err) assert.ErrorContains(t, err, tc.err)
case tc.invalid != "": case tc.invalid != "":
assert.NilError(t, err) assert.NilError(t, err)
assert.Assert(t, cmp.ErrorType(p.Err, reflect.TypeOf(&pluginError{}))) var expectedError *pluginError
assert.Check(t, errors.As(p.Err, &expectedError))
assert.ErrorContains(t, p.Err, tc.invalid) assert.ErrorContains(t, p.Err, tc.invalid)
default: default:
assert.NilError(t, err) assert.NilError(t, err)

View File

@ -127,7 +127,6 @@ func TestContainerListBuildContainerListOptions(t *testing.T) {
func TestContainerListErrors(t *testing.T) { func TestContainerListErrors(t *testing.T) {
testCases := []struct { testCases := []struct {
args []string
flags map[string]string flags map[string]string
containerListFunc func(container.ListOptions) ([]container.Summary, error) containerListFunc func(container.ListOptions) ([]container.Summary, error)
expectedError string expectedError string
@ -157,10 +156,10 @@ func TestContainerListErrors(t *testing.T) {
containerListFunc: tc.containerListFunc, containerListFunc: tc.containerListFunc,
}), }),
) )
cmd.SetArgs(tc.args)
for key, value := range tc.flags { for key, value := range tc.flags {
assert.Check(t, cmd.Flags().Set(key, value)) assert.Check(t, cmd.Flags().Set(key, value))
} }
cmd.SetArgs([]string{})
cmd.SetOut(io.Discard) cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard) cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError) assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
@ -180,6 +179,9 @@ func TestContainerListWithoutFormat(t *testing.T) {
}, },
}) })
cmd := newListCommand(cli) cmd := newListCommand(cli)
cmd.SetArgs([]string{})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.NilError(t, cmd.Execute()) assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "container-list-without-format.golden") golden.Assert(t, cli.OutBuffer().String(), "container-list-without-format.golden")
} }
@ -194,6 +196,9 @@ func TestContainerListNoTrunc(t *testing.T) {
}, },
}) })
cmd := newListCommand(cli) cmd := newListCommand(cli)
cmd.SetArgs([]string{})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.Check(t, cmd.Flags().Set("no-trunc", "true")) assert.Check(t, cmd.Flags().Set("no-trunc", "true"))
assert.NilError(t, cmd.Execute()) assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "container-list-without-format-no-trunc.golden") golden.Assert(t, cli.OutBuffer().String(), "container-list-without-format-no-trunc.golden")
@ -210,6 +215,9 @@ func TestContainerListNamesMultipleTime(t *testing.T) {
}, },
}) })
cmd := newListCommand(cli) cmd := newListCommand(cli)
cmd.SetArgs([]string{})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.Check(t, cmd.Flags().Set("format", "{{.Names}} {{.Names}}")) assert.Check(t, cmd.Flags().Set("format", "{{.Names}} {{.Names}}"))
assert.NilError(t, cmd.Execute()) assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "container-list-format-name-name.golden") golden.Assert(t, cli.OutBuffer().String(), "container-list-format-name-name.golden")
@ -226,6 +234,9 @@ func TestContainerListFormatTemplateWithArg(t *testing.T) {
}, },
}) })
cmd := newListCommand(cli) cmd := newListCommand(cli)
cmd.SetArgs([]string{})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.Check(t, cmd.Flags().Set("format", `{{.Names}} {{.Label "some.label"}}`)) assert.Check(t, cmd.Flags().Set("format", `{{.Names}} {{.Label "some.label"}}`))
assert.NilError(t, cmd.Execute()) assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "container-list-format-with-arg.golden") golden.Assert(t, cli.OutBuffer().String(), "container-list-format-with-arg.golden")
@ -275,6 +286,9 @@ func TestContainerListFormatSizeSetsOption(t *testing.T) {
}, },
}) })
cmd := newListCommand(cli) cmd := newListCommand(cli)
cmd.SetArgs([]string{})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.Check(t, cmd.Flags().Set("format", tc.format)) assert.Check(t, cmd.Flags().Set("format", tc.format))
if tc.sizeFlag != "" { if tc.sizeFlag != "" {
assert.Check(t, cmd.Flags().Set("size", tc.sizeFlag)) assert.Check(t, cmd.Flags().Set("size", tc.sizeFlag))
@ -297,6 +311,9 @@ func TestContainerListWithConfigFormat(t *testing.T) {
PsFormat: "{{ .Names }} {{ .Image }} {{ .Labels }} {{ .Size}}", PsFormat: "{{ .Names }} {{ .Image }} {{ .Labels }} {{ .Size}}",
}) })
cmd := newListCommand(cli) cmd := newListCommand(cli)
cmd.SetArgs([]string{})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.NilError(t, cmd.Execute()) assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "container-list-with-config-format.golden") golden.Assert(t, cli.OutBuffer().String(), "container-list-with-config-format.golden")
} }
@ -314,6 +331,9 @@ func TestContainerListWithFormat(t *testing.T) {
t.Run("with format", func(t *testing.T) { t.Run("with format", func(t *testing.T) {
cli.OutBuffer().Reset() cli.OutBuffer().Reset()
cmd := newListCommand(cli) cmd := newListCommand(cli)
cmd.SetArgs([]string{})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.Check(t, cmd.Flags().Set("format", "{{ .Names }} {{ .Image }} {{ .Labels }}")) assert.Check(t, cmd.Flags().Set("format", "{{ .Names }} {{ .Image }} {{ .Labels }}"))
assert.NilError(t, cmd.Execute()) assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "container-list-with-format.golden") golden.Assert(t, cli.OutBuffer().String(), "container-list-with-format.golden")
@ -322,6 +342,9 @@ func TestContainerListWithFormat(t *testing.T) {
t.Run("with format and quiet", func(t *testing.T) { t.Run("with format and quiet", func(t *testing.T) {
cli.OutBuffer().Reset() cli.OutBuffer().Reset()
cmd := newListCommand(cli) cmd := newListCommand(cli)
cmd.SetArgs([]string{})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.Check(t, cmd.Flags().Set("format", "{{ .Names }} {{ .Image }} {{ .Labels }}")) assert.Check(t, cmd.Flags().Set("format", "{{ .Names }} {{ .Image }} {{ .Labels }}"))
assert.Check(t, cmd.Flags().Set("quiet", "true")) assert.Check(t, cmd.Flags().Set("quiet", "true"))
assert.NilError(t, cmd.Execute()) assert.NilError(t, cmd.Execute())

View File

@ -21,6 +21,7 @@ func TestContainerPrunePromptTermination(t *testing.T) {
}, },
}) })
cmd := NewPruneCommand(cli) cmd := NewPruneCommand(cli)
cmd.SetArgs([]string{})
cmd.SetOut(io.Discard) cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard) cmd.SetErr(io.Discard)
test.TerminatePrompt(ctx, t, cmd, cli) test.TerminatePrompt(ctx, t, cmd, cli)

View File

@ -38,7 +38,7 @@ func waitFn(cid string) (<-chan container.WaitResponse, <-chan error) {
} }
func TestWaitExitOrRemoved(t *testing.T) { func TestWaitExitOrRemoved(t *testing.T) {
testcases := []struct { tests := []struct {
cid string cid string
exitCode int exitCode int
}{ }{
@ -61,9 +61,11 @@ func TestWaitExitOrRemoved(t *testing.T) {
} }
client := &fakeClient{waitFunc: waitFn, Version: api.DefaultVersion} client := &fakeClient{waitFunc: waitFn, Version: api.DefaultVersion}
for _, testcase := range testcases { for _, tc := range tests {
statusC := waitExitOrRemoved(context.Background(), client, testcase.cid, true) t.Run(tc.cid, func(t *testing.T) {
exitCode := <-statusC statusC := waitExitOrRemoved(context.Background(), client, tc.cid, true)
assert.Check(t, is.Equal(testcase.exitCode, exitCode)) exitCode := <-statusC
assert.Check(t, is.Equal(tc.exitCode, exitCode))
})
} }
} }

View File

@ -8,7 +8,6 @@ import (
"github.com/docker/cli/cli/config/configfile" "github.com/docker/cli/cli/config/configfile"
"github.com/docker/docker/errdefs" "github.com/docker/docker/errdefs"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
) )
func TestRemove(t *testing.T) { func TestRemove(t *testing.T) {
@ -18,7 +17,7 @@ func TestRemove(t *testing.T) {
_, err := cli.ContextStore().GetMetadata("current") _, err := cli.ContextStore().GetMetadata("current")
assert.NilError(t, err) assert.NilError(t, err)
_, err = cli.ContextStore().GetMetadata("other") _, err = cli.ContextStore().GetMetadata("other")
assert.Check(t, is.ErrorType(err, errdefs.IsNotFound)) assert.Check(t, errdefs.IsNotFound(err))
} }
func TestRemoveNotAContext(t *testing.T) { func TestRemoveNotAContext(t *testing.T) {

View File

@ -47,7 +47,7 @@ func TestUse(t *testing.T) {
func TestUseNoExist(t *testing.T) { func TestUseNoExist(t *testing.T) {
cli := makeFakeCli(t) cli := makeFakeCli(t)
err := newUseCommand(cli).RunE(nil, []string{"test"}) err := newUseCommand(cli).RunE(nil, []string{"test"})
assert.Check(t, is.ErrorType(err, errdefs.IsNotFound)) assert.Check(t, errdefs.IsNotFound(err))
} }
// TestUseDefaultWithoutConfigFile verifies that the CLI does not create // TestUseDefaultWithoutConfigFile verifies that the CLI does not create

View File

@ -14,7 +14,6 @@ import (
"github.com/docker/docker/errdefs" "github.com/docker/docker/errdefs"
"github.com/docker/go-connections/tlsconfig" "github.com/docker/go-connections/tlsconfig"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/golden" "gotest.tools/v3/golden"
) )
@ -158,7 +157,7 @@ func TestErrCreateDefault(t *testing.T) {
Metadata: testContext{Bar: "baz"}, Metadata: testContext{Bar: "baz"},
Name: "default", Name: "default",
}) })
assert.Check(t, is.ErrorType(err, errdefs.IsInvalidParameter)) assert.Check(t, errdefs.IsInvalidParameter(err))
assert.Error(t, err, "default context cannot be created nor updated") assert.Error(t, err, "default context cannot be created nor updated")
} }
@ -166,7 +165,7 @@ func TestErrRemoveDefault(t *testing.T) {
meta := testDefaultMetadata() meta := testDefaultMetadata()
s := testStore(t, meta, store.ContextTLSData{}) s := testStore(t, meta, store.ContextTLSData{})
err := s.Remove("default") err := s.Remove("default")
assert.Check(t, is.ErrorType(err, errdefs.IsInvalidParameter)) assert.Check(t, errdefs.IsInvalidParameter(err))
assert.Error(t, err, "default context cannot be removed") assert.Error(t, err, "default context cannot be removed")
} }
@ -174,5 +173,5 @@ func TestErrTLSDataError(t *testing.T) {
meta := testDefaultMetadata() meta := testDefaultMetadata()
s := testStore(t, meta, store.ContextTLSData{}) s := testStore(t, meta, store.ContextTLSData{})
_, err := s.GetTLSData("default", "noop", "noop") _, err := s.GetTLSData("default", "noop", "noop")
assert.Check(t, is.ErrorType(err, errdefs.IsNotFound)) assert.Check(t, errdefs.IsNotFound(err))
} }

View File

@ -5,6 +5,7 @@ package loader
import ( import (
"bytes" "bytes"
"errors"
"os" "os"
"runtime" "runtime"
"sort" "sort"
@ -878,7 +879,8 @@ services:
service: foo service: foo
`) `)
assert.ErrorType(t, err, &ForbiddenPropertiesError{}) var expectedErr *ForbiddenPropertiesError
assert.Check(t, errors.As(err, &expectedErr))
props := err.(*ForbiddenPropertiesError).Properties props := err.(*ForbiddenPropertiesError).Properties
assert.Check(t, is.Len(props, 2)) assert.Check(t, is.Len(props, 2))

View File

@ -4,6 +4,7 @@
package template package template
import ( import (
"errors"
"fmt" "fmt"
"testing" "testing"
@ -128,7 +129,8 @@ func TestMandatoryVariableErrors(t *testing.T) {
for _, tc := range testCases { for _, tc := range testCases {
_, err := Substitute(tc.template, defaultMapping) _, err := Substitute(tc.template, defaultMapping)
assert.Check(t, is.ErrorContains(err, tc.expectedError)) assert.Check(t, is.ErrorContains(err, tc.expectedError))
assert.Check(t, is.ErrorType(err, &InvalidTemplateError{})) var expectedError *InvalidTemplateError
assert.Check(t, errors.As(err, &expectedError))
} }
} }

View File

@ -26,7 +26,7 @@ func testMetadata(name string) Metadata {
func TestMetadataGetNotExisting(t *testing.T) { func TestMetadataGetNotExisting(t *testing.T) {
testee := metadataStore{root: t.TempDir(), config: testCfg} testee := metadataStore{root: t.TempDir(), config: testCfg}
_, err := testee.get("noexist") _, err := testee.get("noexist")
assert.ErrorType(t, err, errdefs.IsNotFound) assert.Check(t, errdefs.IsNotFound(err))
} }
func TestMetadataCreateGetRemove(t *testing.T) { func TestMetadataCreateGetRemove(t *testing.T) {
@ -60,7 +60,7 @@ func TestMetadataCreateGetRemove(t *testing.T) {
assert.NilError(t, testee.remove("test-context")) assert.NilError(t, testee.remove("test-context"))
assert.NilError(t, testee.remove("test-context")) // support duplicate remove assert.NilError(t, testee.remove("test-context")) // support duplicate remove
_, err = testee.get("test-context") _, err = testee.get("test-context")
assert.ErrorType(t, err, errdefs.IsNotFound) assert.Check(t, errdefs.IsNotFound(err))
} }
func TestMetadataRespectJsonAnnotation(t *testing.T) { func TestMetadataRespectJsonAnnotation(t *testing.T) {

View File

@ -107,7 +107,7 @@ func TestRemove(t *testing.T) {
})) }))
assert.NilError(t, s.Remove("source")) assert.NilError(t, s.Remove("source"))
_, err = s.GetMetadata("source") _, err = s.GetMetadata("source")
assert.Check(t, is.ErrorType(err, errdefs.IsNotFound)) assert.Check(t, errdefs.IsNotFound(err))
f, err := s.ListTLSFiles("source") f, err := s.ListTLSFiles("source")
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, 0, len(f)) assert.Equal(t, 0, len(f))
@ -122,7 +122,7 @@ func TestListEmptyStore(t *testing.T) {
func TestErrHasCorrectContext(t *testing.T) { func TestErrHasCorrectContext(t *testing.T) {
_, err := New(t.TempDir(), testCfg).GetMetadata("no-exists") _, err := New(t.TempDir(), testCfg).GetMetadata("no-exists")
assert.ErrorContains(t, err, "no-exists") assert.ErrorContains(t, err, "no-exists")
assert.Check(t, is.ErrorType(err, errdefs.IsNotFound)) assert.Check(t, errdefs.IsNotFound(err))
} }
func TestDetectImportContentType(t *testing.T) { func TestDetectImportContentType(t *testing.T) {

View File

@ -13,7 +13,7 @@ func TestTlsCreateUpdateGetRemove(t *testing.T) {
const contextName = "test-ctx" const contextName = "test-ctx"
_, err := testee.getData(contextName, "test-ep", "test-data") _, err := testee.getData(contextName, "test-ep", "test-data")
assert.ErrorType(t, err, errdefs.IsNotFound) assert.Check(t, errdefs.IsNotFound(err))
err = testee.createOrUpdate(contextName, "test-ep", "test-data", []byte("data")) err = testee.createOrUpdate(contextName, "test-ep", "test-data", []byte("data"))
assert.NilError(t, err) assert.NilError(t, err)
@ -29,7 +29,7 @@ func TestTlsCreateUpdateGetRemove(t *testing.T) {
err = testee.removeEndpoint(contextName, "test-ep") err = testee.removeEndpoint(contextName, "test-ep")
assert.NilError(t, err) assert.NilError(t, err)
_, err = testee.getData(contextName, "test-ep", "test-data") _, err = testee.getData(contextName, "test-ep", "test-data")
assert.ErrorType(t, err, errdefs.IsNotFound) assert.Check(t, errdefs.IsNotFound(err))
} }
func TestTlsListAndBatchRemove(t *testing.T) { func TestTlsListAndBatchRemove(t *testing.T) {

View File

@ -12,38 +12,50 @@ Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
## Description ## Description
A full image name has the following format and components: A Docker image reference consists of several components that describe where the
image is stored and its identity. These components are:
`[HOST[:PORT_NUMBER]/]PATH` ```text
[HOST[:PORT]/]NAMESPACE/REPOSITORY[:TAG]
```
- `HOST`: The optional registry hostname specifies where the image is located. `HOST`
The hostname must comply with standard DNS rules, but may not contain : Specifies the registry location where the image resides. If omitted, Docker
underscores. If you don't specify a hostname, the command uses Docker's public defaults to Docker Hub (`docker.io`).
registry at `registry-1.docker.io` by default. Note that `docker.io` is the
canonical reference for Docker's public registry.
- `PORT_NUMBER`: If a hostname is present, it may optionally be followed by a
registry port number in the format `:8080`.
- `PATH`: The path consists of slash-separated components. Each
component may contain lowercase letters, digits and separators. A separator is
defined as a period, one or two underscores, or one or more hyphens. A component
may not start or end with a separator. While the
[OCI Distribution Specification](https://github.com/opencontainers/distribution-spec)
supports more than two slash-separated components, most registries only support
two slash-separated components. For Docker's public registry, the path format is
as follows:
- `[NAMESPACE/]REPOSITORY`: The first, optional component is typically a
user's or an organization's namespace. The second, mandatory component is the
repository name. When the namespace is not present, Docker uses `library`
as the default namespace.
After the image name, the optional `TAG` is a custom, human-readable manifest `PORT`
identifier that's typically a specific version or variant of an image. The tag : An optional port number for the registry, if necessary (for example, `:5000`).
must be valid ASCII and can contain lowercase and uppercase letters, digits,
underscores, periods, and hyphens. It can't start with a period or hyphen and
must be no longer than 128 characters. If you don't specify a tag, the command uses `latest` by default.
You can group your images together using names and tags, and then `NAMESPACE/REPOSITORY`
[push](image_push.md) them to a registry. : The namespace (optional) usually represents a user or organization. The
repository is required and identifies the specific image. If the namespace is
omitted, Docker defaults to `library`, the namespace reserved for Docker
Official Images.
`TAG`
: An optional identifier used to specify a particular version or variant of the
image. If no tag is provided, Docker defaults to `latest`.
### Example image references
`example.com:5000/team/my-app:2.0`
- Host: `example.com`
- Port: `5000`
- Namespace: `team`
- Repository: `my-app`
- Tag: `2.0`
`alpine`
- Host: `docker.io` (default)
- Namespace: `library` (default)
- Repository: `alpine`
- Tag: `latest` (default)
For more information on the structure and rules of image naming, refer to the
[Distribution reference](https://pkg.go.dev/github.com/distribution/reference#pkg-overview)
as the canonical definition of the format.
## Examples ## Examples

View File

@ -26,7 +26,7 @@ per Docker object type. Different event types have different scopes. Local
scoped events are only seen on the node they take place on, and Swarm scoped scoped events are only seen on the node they take place on, and Swarm scoped
events are seen on all managers. events are seen on all managers.
Only the last 1000 log events are returned. You can use filters to further limit Only the last 256 log events are returned. You can use filters to further limit
the number of events returned. the number of events returned.
### Object types ### Object types
@ -156,7 +156,7 @@ that have elapsed since January 1, 1970 (midnight UTC/GMT), not counting leap
seconds (aka Unix epoch or Unix time), and the optional .nanoseconds field is a seconds (aka Unix epoch or Unix time), and the optional .nanoseconds field is a
fraction of a second no more than nine digits long. fraction of a second no more than nine digits long.
Only the last 1000 log events are returned. You can use filters to further limit Only the last 256 log events are returned. You can use filters to further limit
the number of events returned. the number of events returned.
#### <a name="filter"></a> Filtering (--filter) #### <a name="filter"></a> Filtering (--filter)

View File

@ -89,3 +89,55 @@ func TestParseTruncateFunction(t *testing.T) {
}) })
} }
} }
func TestHeaderFunctions(t *testing.T) {
const source = "hello world"
tests := []struct {
doc string
template string
}{
{
doc: "json",
template: `{{ json .}}`,
},
{
doc: "split",
template: `{{ split . ","}}`,
},
{
doc: "join",
template: `{{ join . ","}}`,
},
{
doc: "title",
template: `{{ title .}}`,
},
{
doc: "lower",
template: `{{ lower .}}`,
},
{
doc: "upper",
template: `{{ upper .}}`,
},
{
doc: "truncate",
template: `{{ truncate . 2}}`,
},
}
for _, tc := range tests {
t.Run(tc.doc, func(t *testing.T) {
tmpl, err := New("").Funcs(HeaderFunctions).Parse(tc.template)
assert.NilError(t, err)
var b bytes.Buffer
assert.NilError(t, tmpl.Execute(&b, source))
// All header-functions are currently stubs, and don't modify the input.
expected := source
assert.Equal(t, expected, b.String())
})
}
}

View File

@ -25,7 +25,7 @@ require (
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/mattn/go-runewidth v0.0.15 github.com/mattn/go-runewidth v0.0.15
github.com/moby/patternmatcher v0.6.0 github.com/moby/patternmatcher v0.6.0
github.com/moby/swarmkit/v2 v2.0.0-20240611172349-ea1a7cec35cb github.com/moby/swarmkit/v2 v2.0.0-20241017191044-e8ecf83ee08e
github.com/moby/sys/capability v0.3.0 github.com/moby/sys/capability v0.3.0
github.com/moby/sys/sequential v0.6.0 github.com/moby/sys/sequential v0.6.0
github.com/moby/sys/signal v0.7.1 github.com/moby/sys/signal v0.7.1

View File

@ -180,8 +180,8 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
github.com/moby/swarmkit/v2 v2.0.0-20240611172349-ea1a7cec35cb h1:1UTTg2EgO3nuyV03wREDzldqqePzQ4+0a5G1C1y1bIo= github.com/moby/swarmkit/v2 v2.0.0-20241017191044-e8ecf83ee08e h1:1yC8fRqStY6NirU/swI74fsrHvZVMbtxsHcvl8YpzDg=
github.com/moby/swarmkit/v2 v2.0.0-20240611172349-ea1a7cec35cb/go.mod h1:kNy225f/gWAnF8wPftteMc5nbAHhrH+HUfvyjmhFjeQ= github.com/moby/swarmkit/v2 v2.0.0-20241017191044-e8ecf83ee08e/go.mod h1:mTTGIAz/59OGZR5Qe+QByIe3Nxc+sSuJkrsStFhr6Lg=
github.com/moby/sys/capability v0.3.0 h1:kEP+y6te0gEXIaeQhIi0s7vKs/w0RPoH1qPa6jROcVg= github.com/moby/sys/capability v0.3.0 h1:kEP+y6te0gEXIaeQhIi0s7vKs/w0RPoH1qPa6jROcVg=
github.com/moby/sys/capability v0.3.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I= github.com/moby/sys/capability v0.3.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=

2
vendor/modules.txt vendored
View File

@ -197,7 +197,7 @@ github.com/moby/docker-image-spec/specs-go/v1
## explicit; go 1.19 ## explicit; go 1.19
github.com/moby/patternmatcher github.com/moby/patternmatcher
github.com/moby/patternmatcher/ignorefile github.com/moby/patternmatcher/ignorefile
# github.com/moby/swarmkit/v2 v2.0.0-20240611172349-ea1a7cec35cb # github.com/moby/swarmkit/v2 v2.0.0-20241017191044-e8ecf83ee08e
## explicit; go 1.18 ## explicit; go 1.18
github.com/moby/swarmkit/v2/api github.com/moby/swarmkit/v2/api
github.com/moby/swarmkit/v2/api/deepcopy github.com/moby/swarmkit/v2/api/deepcopy