2018-03-06 05:15:18 -05:00
|
|
|
package image
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/docker/cli/e2e/internal/fixtures"
|
2018-05-17 07:11:59 -04:00
|
|
|
"github.com/docker/cli/internal/test/environment"
|
2018-03-06 05:15:18 -05:00
|
|
|
"github.com/docker/cli/internal/test/output"
|
2020-02-22 12:12:14 -05:00
|
|
|
"gotest.tools/v3/assert"
|
|
|
|
"gotest.tools/v3/fs"
|
|
|
|
"gotest.tools/v3/golden"
|
|
|
|
"gotest.tools/v3/icmd"
|
|
|
|
"gotest.tools/v3/skip"
|
2018-03-06 05:15:18 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
notary = "/usr/local/bin/notary"
|
|
|
|
|
|
|
|
pubkey1 = "./testdata/notary/delgkey1.crt"
|
|
|
|
privkey1 = "./testdata/notary/delgkey1.key"
|
|
|
|
pubkey2 = "./testdata/notary/delgkey2.crt"
|
|
|
|
privkey2 = "./testdata/notary/delgkey2.key"
|
|
|
|
pubkey3 = "./testdata/notary/delgkey3.crt"
|
|
|
|
privkey3 = "./testdata/notary/delgkey3.key"
|
|
|
|
pubkey4 = "./testdata/notary/delgkey4.crt"
|
|
|
|
privkey4 = "./testdata/notary/delgkey4.key"
|
|
|
|
)
|
|
|
|
|
implement docker push -a/--all-tags
The `docker push` command up until [v0.9.1](https://github.com/moby/moby/blob/v0.9.1/api/client.go#L998)
always pushed all tags of a given image, so `docker push foo/bar` would push (e.g.)
all of `foo/bar:latest`, `foo:/bar:v1`, `foo/bar:v1.0.0`.
Pushing all tags of an image was not desirable in many case, so docker v0.10.0
enhanced `docker push` to optionally specify a tag to push (`docker push foo/bar:v1`)
(see https://github.com/moby/moby/issues/3411 and the pull request that implemented
this: https://github.com/moby/moby/pull/4948).
This behavior exists up until today, and is confusing, because unlike other commands,
`docker push` does not default to use the `:latest` tag when omitted, but instead
makes it push "all tags of the image"
For example, in the following situation;
```
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thajeztah/myimage latest b534869c81f0 41 hours ago 1.22MB
```
Running `docker push thajeztah/myimage` seemingly does the expected behavior (it
pushes `thajeztah/myimage:latest` to Docker Hub), however, it does not so for the
reason expected (`:latest` being the default tag), but because `:latest` happens
to be the only tag present for the `thajeztah/myimage` image.
If another tag exists for the image:
```
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thajeztah/myimage latest b534869c81f0 41 hours ago 1.22MB
thajeztah/myimage v1.0.0 b534869c81f0 41 hours ago 1.22MB
```
Running the same command (`docker push thajeztah/myimage`) will push _both_ images
to Docker Hub.
> Note that the behavior described above is currently not (clearly) documented;
> the `docker push` reference documentation (https://docs.docker.com/engine/reference/commandline/push/)
does not mention that omitting the tag will push all tags
This patch changes the default behavior, and if no tag is specified, `:latest` is
assumed. To push _all_ tags, a new flag (`-a` / `--all-tags`) is added, similar
to the flag that's present on `docker pull`.
With this change:
- `docker push myname/myimage` will be the equivalent of `docker push myname/myimage:latest`
- to push all images, the user needs to set a flag (`--all-tags`), so `docker push --all-tags myname/myimage:latest`
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-12-09 08:48:42 -05:00
|
|
|
func TestPushAllTags(t *testing.T) {
|
|
|
|
skip.If(t, environment.RemoteDaemon())
|
|
|
|
|
2023-02-24 06:36:53 -05:00
|
|
|
// Compared digests are linux/amd64 specific.
|
|
|
|
// TODO: Fix this test and make it work on all platforms.
|
|
|
|
environment.SkipIfNotPlatform(t, "linux/amd64")
|
|
|
|
|
implement docker push -a/--all-tags
The `docker push` command up until [v0.9.1](https://github.com/moby/moby/blob/v0.9.1/api/client.go#L998)
always pushed all tags of a given image, so `docker push foo/bar` would push (e.g.)
all of `foo/bar:latest`, `foo:/bar:v1`, `foo/bar:v1.0.0`.
Pushing all tags of an image was not desirable in many case, so docker v0.10.0
enhanced `docker push` to optionally specify a tag to push (`docker push foo/bar:v1`)
(see https://github.com/moby/moby/issues/3411 and the pull request that implemented
this: https://github.com/moby/moby/pull/4948).
This behavior exists up until today, and is confusing, because unlike other commands,
`docker push` does not default to use the `:latest` tag when omitted, but instead
makes it push "all tags of the image"
For example, in the following situation;
```
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thajeztah/myimage latest b534869c81f0 41 hours ago 1.22MB
```
Running `docker push thajeztah/myimage` seemingly does the expected behavior (it
pushes `thajeztah/myimage:latest` to Docker Hub), however, it does not so for the
reason expected (`:latest` being the default tag), but because `:latest` happens
to be the only tag present for the `thajeztah/myimage` image.
If another tag exists for the image:
```
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thajeztah/myimage latest b534869c81f0 41 hours ago 1.22MB
thajeztah/myimage v1.0.0 b534869c81f0 41 hours ago 1.22MB
```
Running the same command (`docker push thajeztah/myimage`) will push _both_ images
to Docker Hub.
> Note that the behavior described above is currently not (clearly) documented;
> the `docker push` reference documentation (https://docs.docker.com/engine/reference/commandline/push/)
does not mention that omitting the tag will push all tags
This patch changes the default behavior, and if no tag is specified, `:latest` is
assumed. To push _all_ tags, a new flag (`-a` / `--all-tags`) is added, similar
to the flag that's present on `docker pull`.
With this change:
- `docker push myname/myimage` will be the equivalent of `docker push myname/myimage:latest`
- to push all images, the user needs to set a flag (`--all-tags`), so `docker push --all-tags myname/myimage:latest`
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-12-09 08:48:42 -05:00
|
|
|
_ = createImage(t, "push-all-tags", "latest", "v1", "v1.0", "v1.0.1")
|
|
|
|
result := icmd.RunCmd(icmd.Command("docker", "push", "--all-tags", registryPrefix+"/push-all-tags"))
|
|
|
|
|
|
|
|
result.Assert(t, icmd.Success)
|
|
|
|
golden.Assert(t, result.Stderr(), "push-with-content-trust-err.golden")
|
|
|
|
output.Assert(t, result.Stdout(), map[int]func(string) error{
|
|
|
|
0: output.Equals("The push refers to repository [registry:5000/push-all-tags]"),
|
2023-02-23 09:41:54 -05:00
|
|
|
1: output.Equals("7cd52847ad77: Preparing"),
|
|
|
|
3: output.Equals("latest: digest: sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501 size: 528"),
|
|
|
|
6: output.Equals("v1: digest: sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501 size: 528"),
|
|
|
|
9: output.Equals("v1.0: digest: sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501 size: 528"),
|
|
|
|
12: output.Equals("v1.0.1: digest: sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501 size: 528"),
|
implement docker push -a/--all-tags
The `docker push` command up until [v0.9.1](https://github.com/moby/moby/blob/v0.9.1/api/client.go#L998)
always pushed all tags of a given image, so `docker push foo/bar` would push (e.g.)
all of `foo/bar:latest`, `foo:/bar:v1`, `foo/bar:v1.0.0`.
Pushing all tags of an image was not desirable in many case, so docker v0.10.0
enhanced `docker push` to optionally specify a tag to push (`docker push foo/bar:v1`)
(see https://github.com/moby/moby/issues/3411 and the pull request that implemented
this: https://github.com/moby/moby/pull/4948).
This behavior exists up until today, and is confusing, because unlike other commands,
`docker push` does not default to use the `:latest` tag when omitted, but instead
makes it push "all tags of the image"
For example, in the following situation;
```
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thajeztah/myimage latest b534869c81f0 41 hours ago 1.22MB
```
Running `docker push thajeztah/myimage` seemingly does the expected behavior (it
pushes `thajeztah/myimage:latest` to Docker Hub), however, it does not so for the
reason expected (`:latest` being the default tag), but because `:latest` happens
to be the only tag present for the `thajeztah/myimage` image.
If another tag exists for the image:
```
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thajeztah/myimage latest b534869c81f0 41 hours ago 1.22MB
thajeztah/myimage v1.0.0 b534869c81f0 41 hours ago 1.22MB
```
Running the same command (`docker push thajeztah/myimage`) will push _both_ images
to Docker Hub.
> Note that the behavior described above is currently not (clearly) documented;
> the `docker push` reference documentation (https://docs.docker.com/engine/reference/commandline/push/)
does not mention that omitting the tag will push all tags
This patch changes the default behavior, and if no tag is specified, `:latest` is
assumed. To push _all_ tags, a new flag (`-a` / `--all-tags`) is added, similar
to the flag that's present on `docker pull`.
With this change:
- `docker push myname/myimage` will be the equivalent of `docker push myname/myimage:latest`
- to push all images, the user needs to set a flag (`--all-tags`), so `docker push --all-tags myname/myimage:latest`
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-12-09 08:48:42 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2018-03-06 05:15:18 -05:00
|
|
|
func TestPushWithContentTrust(t *testing.T) {
|
2018-05-17 07:11:59 -04:00
|
|
|
skip.If(t, environment.RemoteDaemon())
|
|
|
|
|
2023-02-24 06:36:53 -05:00
|
|
|
// Compared digests are linux/amd64 specific.
|
|
|
|
// TODO: Fix this test and make it work on all platforms.
|
|
|
|
environment.SkipIfNotPlatform(t, "linux/amd64")
|
|
|
|
|
2018-03-06 05:15:18 -05:00
|
|
|
dir := fixtures.SetupConfigFile(t)
|
|
|
|
defer dir.Remove()
|
implement docker push -a/--all-tags
The `docker push` command up until [v0.9.1](https://github.com/moby/moby/blob/v0.9.1/api/client.go#L998)
always pushed all tags of a given image, so `docker push foo/bar` would push (e.g.)
all of `foo/bar:latest`, `foo:/bar:v1`, `foo/bar:v1.0.0`.
Pushing all tags of an image was not desirable in many case, so docker v0.10.0
enhanced `docker push` to optionally specify a tag to push (`docker push foo/bar:v1`)
(see https://github.com/moby/moby/issues/3411 and the pull request that implemented
this: https://github.com/moby/moby/pull/4948).
This behavior exists up until today, and is confusing, because unlike other commands,
`docker push` does not default to use the `:latest` tag when omitted, but instead
makes it push "all tags of the image"
For example, in the following situation;
```
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thajeztah/myimage latest b534869c81f0 41 hours ago 1.22MB
```
Running `docker push thajeztah/myimage` seemingly does the expected behavior (it
pushes `thajeztah/myimage:latest` to Docker Hub), however, it does not so for the
reason expected (`:latest` being the default tag), but because `:latest` happens
to be the only tag present for the `thajeztah/myimage` image.
If another tag exists for the image:
```
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thajeztah/myimage latest b534869c81f0 41 hours ago 1.22MB
thajeztah/myimage v1.0.0 b534869c81f0 41 hours ago 1.22MB
```
Running the same command (`docker push thajeztah/myimage`) will push _both_ images
to Docker Hub.
> Note that the behavior described above is currently not (clearly) documented;
> the `docker push` reference documentation (https://docs.docker.com/engine/reference/commandline/push/)
does not mention that omitting the tag will push all tags
This patch changes the default behavior, and if no tag is specified, `:latest` is
assumed. To push _all_ tags, a new flag (`-a` / `--all-tags`) is added, similar
to the flag that's present on `docker pull`.
With this change:
- `docker push myname/myimage` will be the equivalent of `docker push myname/myimage:latest`
- to push all images, the user needs to set a flag (`--all-tags`), so `docker push --all-tags myname/myimage:latest`
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-12-09 08:48:42 -05:00
|
|
|
image := createImage(t, "trust-push", "latest")
|
2018-03-06 05:15:18 -05:00
|
|
|
|
|
|
|
result := icmd.RunCmd(icmd.Command("docker", "push", image),
|
|
|
|
fixtures.WithConfig(dir.Path()),
|
|
|
|
fixtures.WithTrust,
|
|
|
|
fixtures.WithNotary,
|
|
|
|
fixtures.WithPassphrase("foo", "bar"),
|
|
|
|
)
|
|
|
|
result.Assert(t, icmd.Success)
|
|
|
|
golden.Assert(t, result.Stderr(), "push-with-content-trust-err.golden")
|
|
|
|
output.Assert(t, result.Stdout(), map[int]func(string) error{
|
|
|
|
0: output.Equals("The push refers to repository [registry:5000/trust-push]"),
|
2023-02-23 09:41:54 -05:00
|
|
|
1: output.Equals("7cd52847ad77: Preparing"),
|
|
|
|
3: output.Equals("latest: digest: sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501 size: 528"),
|
2018-03-06 05:15:18 -05:00
|
|
|
4: output.Equals("Signing and pushing trust metadata"),
|
|
|
|
5: output.Equals(`Finished initializing "registry:5000/trust-push"`),
|
|
|
|
6: output.Equals("Successfully signed registry:5000/trust-push:latest"),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-01-24 07:53:24 -05:00
|
|
|
func TestPushQuietErrors(t *testing.T) {
|
|
|
|
result := icmd.RunCmd(icmd.Command("docker", "push", "--quiet", "nosuchimage"))
|
|
|
|
result.Assert(t, icmd.Expected{
|
|
|
|
ExitCode: 1,
|
|
|
|
Err: "An image does not exist locally with the tag: nosuchimage",
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2018-03-06 05:15:18 -05:00
|
|
|
func TestPushWithContentTrustUnreachableServer(t *testing.T) {
|
2018-05-17 07:11:59 -04:00
|
|
|
skip.If(t, environment.RemoteDaemon())
|
|
|
|
|
2018-03-06 05:15:18 -05:00
|
|
|
dir := fixtures.SetupConfigFile(t)
|
|
|
|
defer dir.Remove()
|
implement docker push -a/--all-tags
The `docker push` command up until [v0.9.1](https://github.com/moby/moby/blob/v0.9.1/api/client.go#L998)
always pushed all tags of a given image, so `docker push foo/bar` would push (e.g.)
all of `foo/bar:latest`, `foo:/bar:v1`, `foo/bar:v1.0.0`.
Pushing all tags of an image was not desirable in many case, so docker v0.10.0
enhanced `docker push` to optionally specify a tag to push (`docker push foo/bar:v1`)
(see https://github.com/moby/moby/issues/3411 and the pull request that implemented
this: https://github.com/moby/moby/pull/4948).
This behavior exists up until today, and is confusing, because unlike other commands,
`docker push` does not default to use the `:latest` tag when omitted, but instead
makes it push "all tags of the image"
For example, in the following situation;
```
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thajeztah/myimage latest b534869c81f0 41 hours ago 1.22MB
```
Running `docker push thajeztah/myimage` seemingly does the expected behavior (it
pushes `thajeztah/myimage:latest` to Docker Hub), however, it does not so for the
reason expected (`:latest` being the default tag), but because `:latest` happens
to be the only tag present for the `thajeztah/myimage` image.
If another tag exists for the image:
```
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thajeztah/myimage latest b534869c81f0 41 hours ago 1.22MB
thajeztah/myimage v1.0.0 b534869c81f0 41 hours ago 1.22MB
```
Running the same command (`docker push thajeztah/myimage`) will push _both_ images
to Docker Hub.
> Note that the behavior described above is currently not (clearly) documented;
> the `docker push` reference documentation (https://docs.docker.com/engine/reference/commandline/push/)
does not mention that omitting the tag will push all tags
This patch changes the default behavior, and if no tag is specified, `:latest` is
assumed. To push _all_ tags, a new flag (`-a` / `--all-tags`) is added, similar
to the flag that's present on `docker pull`.
With this change:
- `docker push myname/myimage` will be the equivalent of `docker push myname/myimage:latest`
- to push all images, the user needs to set a flag (`--all-tags`), so `docker push --all-tags myname/myimage:latest`
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-12-09 08:48:42 -05:00
|
|
|
image := createImage(t, "trust-push-unreachable", "latest")
|
2018-03-06 05:15:18 -05:00
|
|
|
|
|
|
|
result := icmd.RunCmd(icmd.Command("docker", "push", image),
|
|
|
|
fixtures.WithConfig(dir.Path()),
|
|
|
|
fixtures.WithTrust,
|
|
|
|
fixtures.WithNotaryServer("https://invalidnotaryserver"),
|
|
|
|
)
|
|
|
|
result.Assert(t, icmd.Expected{
|
|
|
|
ExitCode: 1,
|
|
|
|
Err: "error contacting notary server",
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPushWithContentTrustExistingTag(t *testing.T) {
|
2018-05-17 07:11:59 -04:00
|
|
|
skip.If(t, environment.RemoteDaemon())
|
|
|
|
|
2018-03-06 05:15:18 -05:00
|
|
|
dir := fixtures.SetupConfigFile(t)
|
|
|
|
defer dir.Remove()
|
implement docker push -a/--all-tags
The `docker push` command up until [v0.9.1](https://github.com/moby/moby/blob/v0.9.1/api/client.go#L998)
always pushed all tags of a given image, so `docker push foo/bar` would push (e.g.)
all of `foo/bar:latest`, `foo:/bar:v1`, `foo/bar:v1.0.0`.
Pushing all tags of an image was not desirable in many case, so docker v0.10.0
enhanced `docker push` to optionally specify a tag to push (`docker push foo/bar:v1`)
(see https://github.com/moby/moby/issues/3411 and the pull request that implemented
this: https://github.com/moby/moby/pull/4948).
This behavior exists up until today, and is confusing, because unlike other commands,
`docker push` does not default to use the `:latest` tag when omitted, but instead
makes it push "all tags of the image"
For example, in the following situation;
```
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thajeztah/myimage latest b534869c81f0 41 hours ago 1.22MB
```
Running `docker push thajeztah/myimage` seemingly does the expected behavior (it
pushes `thajeztah/myimage:latest` to Docker Hub), however, it does not so for the
reason expected (`:latest` being the default tag), but because `:latest` happens
to be the only tag present for the `thajeztah/myimage` image.
If another tag exists for the image:
```
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thajeztah/myimage latest b534869c81f0 41 hours ago 1.22MB
thajeztah/myimage v1.0.0 b534869c81f0 41 hours ago 1.22MB
```
Running the same command (`docker push thajeztah/myimage`) will push _both_ images
to Docker Hub.
> Note that the behavior described above is currently not (clearly) documented;
> the `docker push` reference documentation (https://docs.docker.com/engine/reference/commandline/push/)
does not mention that omitting the tag will push all tags
This patch changes the default behavior, and if no tag is specified, `:latest` is
assumed. To push _all_ tags, a new flag (`-a` / `--all-tags`) is added, similar
to the flag that's present on `docker pull`.
With this change:
- `docker push myname/myimage` will be the equivalent of `docker push myname/myimage:latest`
- to push all images, the user needs to set a flag (`--all-tags`), so `docker push --all-tags myname/myimage:latest`
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-12-09 08:48:42 -05:00
|
|
|
image := createImage(t, "trust-push-existing", "latest")
|
2018-03-06 05:15:18 -05:00
|
|
|
|
|
|
|
result := icmd.RunCmd(icmd.Command("docker", "push", image))
|
|
|
|
result.Assert(t, icmd.Success)
|
|
|
|
|
|
|
|
result = icmd.RunCmd(icmd.Command("docker", "push", image),
|
|
|
|
fixtures.WithConfig(dir.Path()),
|
|
|
|
fixtures.WithTrust,
|
|
|
|
fixtures.WithNotary,
|
|
|
|
fixtures.WithPassphrase("foo", "bar"),
|
|
|
|
)
|
|
|
|
result.Assert(t, icmd.Expected{
|
|
|
|
Out: "Signing and pushing trust metadata",
|
|
|
|
})
|
|
|
|
|
|
|
|
// Re-push
|
|
|
|
result = icmd.RunCmd(icmd.Command("docker", "push", image),
|
|
|
|
fixtures.WithConfig(dir.Path()),
|
|
|
|
fixtures.WithTrust,
|
|
|
|
fixtures.WithNotary,
|
|
|
|
fixtures.WithPassphrase("foo", "bar"),
|
|
|
|
)
|
|
|
|
result.Assert(t, icmd.Expected{
|
|
|
|
Out: "Signing and pushing trust metadata",
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPushWithContentTrustReleasesDelegationOnly(t *testing.T) {
|
2018-05-17 07:11:59 -04:00
|
|
|
skip.If(t, environment.RemoteDaemon())
|
|
|
|
|
2018-03-06 05:15:18 -05:00
|
|
|
role := "targets/releases"
|
|
|
|
|
|
|
|
dir := fixtures.SetupConfigFile(t)
|
|
|
|
defer dir.Remove()
|
|
|
|
copyPrivateKey(t, dir.Join("trust", "private"), privkey1)
|
|
|
|
notaryDir := setupNotaryConfig(t, dir)
|
|
|
|
defer notaryDir.Remove()
|
|
|
|
homeDir := fs.NewDir(t, "push_test_home")
|
|
|
|
defer notaryDir.Remove()
|
|
|
|
|
|
|
|
baseRef := fmt.Sprintf("%s/%s", registryPrefix, "trust-push-releases-delegation")
|
|
|
|
targetRef := fmt.Sprintf("%s:%s", baseRef, "latest")
|
|
|
|
|
|
|
|
// Init repository
|
|
|
|
notaryInit(t, notaryDir, homeDir, baseRef)
|
|
|
|
// Add delegation key (public key)
|
|
|
|
notaryAddDelegation(t, notaryDir, homeDir, baseRef, role, pubkey1)
|
|
|
|
// Publish it
|
|
|
|
notaryPublish(t, notaryDir, homeDir, baseRef)
|
|
|
|
// Import private key
|
|
|
|
notaryImportPrivateKey(t, notaryDir, homeDir, baseRef, role, privkey1)
|
|
|
|
|
|
|
|
// Tag & push with content trust
|
|
|
|
icmd.RunCommand("docker", "pull", fixtures.AlpineImage).Assert(t, icmd.Success)
|
|
|
|
icmd.RunCommand("docker", "tag", fixtures.AlpineImage, targetRef).Assert(t, icmd.Success)
|
|
|
|
result := icmd.RunCmd(icmd.Command("docker", "push", targetRef),
|
|
|
|
fixtures.WithConfig(dir.Path()),
|
|
|
|
fixtures.WithTrust,
|
|
|
|
fixtures.WithNotary,
|
|
|
|
fixtures.WithPassphrase("foo", "foo"),
|
|
|
|
)
|
|
|
|
result.Assert(t, icmd.Expected{
|
|
|
|
Out: "Signing and pushing trust metadata",
|
|
|
|
})
|
|
|
|
|
|
|
|
targetsInRole := notaryListTargetsInRole(t, notaryDir, homeDir, baseRef, role)
|
|
|
|
assert.Assert(t, targetsInRole["latest"] == role, "%v", targetsInRole)
|
|
|
|
targetsInRole = notaryListTargetsInRole(t, notaryDir, homeDir, baseRef, "targets")
|
|
|
|
assert.Assert(t, targetsInRole["latest"] != "targets", "%v", targetsInRole)
|
|
|
|
|
|
|
|
result = icmd.RunCmd(icmd.Command("docker", "pull", targetRef),
|
|
|
|
fixtures.WithConfig(dir.Path()),
|
|
|
|
fixtures.WithTrust,
|
|
|
|
fixtures.WithNotary,
|
|
|
|
)
|
|
|
|
result.Assert(t, icmd.Success)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPushWithContentTrustSignsAllFirstLevelRolesWeHaveKeysFor(t *testing.T) {
|
2018-05-17 07:11:59 -04:00
|
|
|
skip.If(t, environment.RemoteDaemon())
|
|
|
|
|
2018-03-06 05:15:18 -05:00
|
|
|
dir := fixtures.SetupConfigFile(t)
|
|
|
|
defer dir.Remove()
|
|
|
|
copyPrivateKey(t, dir.Join("trust", "private"), privkey1)
|
|
|
|
copyPrivateKey(t, dir.Join("trust", "private"), privkey2)
|
|
|
|
copyPrivateKey(t, dir.Join("trust", "private"), privkey3)
|
|
|
|
notaryDir := setupNotaryConfig(t, dir)
|
|
|
|
defer notaryDir.Remove()
|
|
|
|
homeDir := fs.NewDir(t, "push_test_home")
|
|
|
|
defer notaryDir.Remove()
|
|
|
|
|
|
|
|
baseRef := fmt.Sprintf("%s/%s", registryPrefix, "trust-push-releases-first-roles")
|
|
|
|
targetRef := fmt.Sprintf("%s:%s", baseRef, "latest")
|
|
|
|
|
|
|
|
// Init repository
|
|
|
|
notaryInit(t, notaryDir, homeDir, baseRef)
|
|
|
|
// Add delegation key (public key)
|
|
|
|
notaryAddDelegation(t, notaryDir, homeDir, baseRef, "targets/role1", pubkey1)
|
|
|
|
notaryAddDelegation(t, notaryDir, homeDir, baseRef, "targets/role2", pubkey2)
|
|
|
|
notaryAddDelegation(t, notaryDir, homeDir, baseRef, "targets/role3", pubkey3)
|
|
|
|
notaryAddDelegation(t, notaryDir, homeDir, baseRef, "targets/role1/subrole", pubkey3)
|
|
|
|
// Import private key
|
|
|
|
notaryImportPrivateKey(t, notaryDir, homeDir, baseRef, "targets/role1", privkey1)
|
|
|
|
notaryImportPrivateKey(t, notaryDir, homeDir, baseRef, "targets/role2", privkey2)
|
|
|
|
notaryImportPrivateKey(t, notaryDir, homeDir, baseRef, "targets/role1/subrole", privkey3)
|
|
|
|
// Publish it
|
|
|
|
notaryPublish(t, notaryDir, homeDir, baseRef)
|
|
|
|
|
|
|
|
// Tag & push with content trust
|
|
|
|
icmd.RunCommand("docker", "pull", fixtures.AlpineImage).Assert(t, icmd.Success)
|
|
|
|
icmd.RunCommand("docker", "tag", fixtures.AlpineImage, targetRef).Assert(t, icmd.Success)
|
|
|
|
result := icmd.RunCmd(icmd.Command("docker", "push", targetRef),
|
|
|
|
fixtures.WithConfig(dir.Path()),
|
|
|
|
fixtures.WithTrust,
|
|
|
|
fixtures.WithNotary,
|
|
|
|
fixtures.WithPassphrase("foo", "foo"),
|
|
|
|
)
|
|
|
|
result.Assert(t, icmd.Expected{
|
|
|
|
Out: "Signing and pushing trust metadata",
|
|
|
|
})
|
|
|
|
|
|
|
|
// check to make sure that the target has been added to targets/role1 and targets/role2, and
|
|
|
|
// not targets (because there are delegations) or targets/role3 (due to missing key) or
|
|
|
|
// targets/role1/subrole (due to it being a second level delegation)
|
|
|
|
targetsInRole := notaryListTargetsInRole(t, notaryDir, homeDir, baseRef, "targets/role1")
|
|
|
|
assert.Assert(t, targetsInRole["latest"] == "targets/role1", "%v", targetsInRole)
|
|
|
|
targetsInRole = notaryListTargetsInRole(t, notaryDir, homeDir, baseRef, "targets/role2")
|
|
|
|
assert.Assert(t, targetsInRole["latest"] == "targets/role2", "%v", targetsInRole)
|
|
|
|
targetsInRole = notaryListTargetsInRole(t, notaryDir, homeDir, baseRef, "targets")
|
|
|
|
assert.Assert(t, targetsInRole["latest"] != "targets", "%v", targetsInRole)
|
|
|
|
|
linting: address assorted issues found by gocritic
internal/test/builders/config.go:36:15: captLocal: `ID' should not be capitalized (gocritic)
func ConfigID(ID string) func(config *swarm.Config) {
^
internal/test/builders/secret.go:45:15: captLocal: `ID' should not be capitalized (gocritic)
func SecretID(ID string) func(secret *swarm.Secret) {
^
internal/test/builders/service.go:21:16: captLocal: `ID' should not be capitalized (gocritic)
func ServiceID(ID string) func(*swarm.Service) {
^
cli/command/image/formatter_history.go:100:15: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(c.h.CreatedBy, "\t", " ", -1)` (gocritic)
createdBy := strings.Replace(c.h.CreatedBy, "\t", " ", -1)
^
e2e/image/push_test.go:246:34: badCall: suspicious Join on 1 argument (gocritic)
assert.NilError(t, os.RemoveAll(filepath.Join(dir.Join("trust"))))
^
e2e/image/push_test.go:313:34: badCall: suspicious Join on 1 argument (gocritic)
assert.NilError(t, os.RemoveAll(filepath.Join(dir.Join("trust"))))
^
cli/config/configfile/file_test.go:185:2: assignOp: replace `c.GetAllCallCount = c.GetAllCallCount + 1` with `c.GetAllCallCount++` (gocritic)
c.GetAllCallCount = c.GetAllCallCount + 1
^
cli/command/context/inspect_test.go:20:58: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(si.MetadataPath, `\`, `\\`, -1)` (gocritic)
expected = strings.Replace(expected, "<METADATA_PATH>", strings.Replace(si.MetadataPath, `\`, `\\`, -1), 1)
^
cli/command/context/inspect_test.go:21:53: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(si.TLSPath, `\`, `\\`, -1)` (gocritic)
expected = strings.Replace(expected, "<TLS_PATH>", strings.Replace(si.TLSPath, `\`, `\\`, -1), 1)
^
cli/command/container/formatter_stats.go:119:46: captLocal: `Stats' should not be capitalized (gocritic)
func statsFormatWrite(ctx formatter.Context, Stats []StatsEntry, osType string, trunc bool) error {
^
cli/command/container/stats_helpers.go:209:4: assignOp: replace `blkRead = blkRead + bioEntry.Value` with `blkRead += bioEntry.Value` (gocritic)
blkRead = blkRead + bioEntry.Value
^
cli/command/container/stats_helpers.go:211:4: assignOp: replace `blkWrite = blkWrite + bioEntry.Value` with `blkWrite += bioEntry.Value` (gocritic)
blkWrite = blkWrite + bioEntry.Value
^
cli/command/registry/formatter_search.go:67:10: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(c.s.Description, "\n", " ", -1)` (gocritic)
desc := strings.Replace(c.s.Description, "\n", " ", -1)
^
cli/command/registry/formatter_search.go:68:9: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(desc, "\r", " ", -1)` (gocritic)
desc = strings.Replace(desc, "\r", " ", -1)
^
cli/command/service/list_test.go:164:5: assignOp: replace `tc.doc = tc.doc + " with quiet"` with `tc.doc += " with quiet"` (gocritic)
tc.doc = tc.doc + " with quiet"
^
cli/command/service/progress/progress.go:274:11: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(errMsg, "\n", " ", -1)` (gocritic)
errMsg = strings.Replace(errMsg, "\n", " ", -1)
^
cli/manifest/store/store.go:153:9: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(fileName, "/", "_", -1)` (gocritic)
return strings.Replace(fileName, "/", "_", -1)
^
cli/manifest/store/store.go:152:14: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(ref, ":", "-", -1)` (gocritic)
fileName := strings.Replace(ref, ":", "-", -1)
^
cli/command/plugin/formatter.go:79:10: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(c.p.Config.Description, "\n", "", -1)` (gocritic)
desc := strings.Replace(c.p.Config.Description, "\n", "", -1)
^
cli/command/plugin/formatter.go:80:9: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(desc, "\r", "", -1)` (gocritic)
desc = strings.Replace(desc, "\r", "", -1)
^
cli/compose/convert/service.go:642:23: captLocal: `DNS' should not be capitalized (gocritic)
func convertDNSConfig(DNS []string, DNSSearch []string) *swarm.DNSConfig {
^
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-11-20 07:30:05 -05:00
|
|
|
assert.NilError(t, os.RemoveAll(dir.Join("trust")))
|
2018-03-06 05:15:18 -05:00
|
|
|
// Try to pull, should fail because non of these are the release role
|
|
|
|
// FIXME(vdemeester) should be unit test
|
|
|
|
result = icmd.RunCmd(icmd.Command("docker", "pull", targetRef),
|
|
|
|
fixtures.WithConfig(dir.Path()),
|
|
|
|
fixtures.WithTrust,
|
|
|
|
fixtures.WithNotary,
|
|
|
|
)
|
|
|
|
result.Assert(t, icmd.Expected{
|
|
|
|
ExitCode: 1,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPushWithContentTrustSignsForRolesWithKeysAndValidPaths(t *testing.T) {
|
2018-05-17 07:11:59 -04:00
|
|
|
skip.If(t, environment.RemoteDaemon())
|
|
|
|
|
2018-03-06 05:15:18 -05:00
|
|
|
dir := fixtures.SetupConfigFile(t)
|
|
|
|
defer dir.Remove()
|
|
|
|
copyPrivateKey(t, dir.Join("trust", "private"), privkey1)
|
|
|
|
copyPrivateKey(t, dir.Join("trust", "private"), privkey2)
|
|
|
|
copyPrivateKey(t, dir.Join("trust", "private"), privkey3)
|
|
|
|
copyPrivateKey(t, dir.Join("trust", "private"), privkey4)
|
|
|
|
notaryDir := setupNotaryConfig(t, dir)
|
|
|
|
defer notaryDir.Remove()
|
|
|
|
homeDir := fs.NewDir(t, "push_test_home")
|
|
|
|
defer notaryDir.Remove()
|
|
|
|
|
|
|
|
baseRef := fmt.Sprintf("%s/%s", registryPrefix, "trust-push-releases-keys-valid-paths")
|
|
|
|
targetRef := fmt.Sprintf("%s:%s", baseRef, "latest")
|
|
|
|
|
|
|
|
// Init repository
|
|
|
|
notaryInit(t, notaryDir, homeDir, baseRef)
|
|
|
|
// Add delegation key (public key)
|
|
|
|
notaryAddDelegation(t, notaryDir, homeDir, baseRef, "targets/role1", pubkey1, "l", "z")
|
|
|
|
notaryAddDelegation(t, notaryDir, homeDir, baseRef, "targets/role2", pubkey2, "x", "y")
|
|
|
|
notaryAddDelegation(t, notaryDir, homeDir, baseRef, "targets/role3", pubkey3, "latest")
|
|
|
|
notaryAddDelegation(t, notaryDir, homeDir, baseRef, "targets/role4", pubkey4, "latest")
|
|
|
|
// Import private keys (except 3rd key)
|
|
|
|
notaryImportPrivateKey(t, notaryDir, homeDir, baseRef, "targets/role1", privkey1)
|
|
|
|
notaryImportPrivateKey(t, notaryDir, homeDir, baseRef, "targets/role2", privkey2)
|
|
|
|
notaryImportPrivateKey(t, notaryDir, homeDir, baseRef, "targets/role4", privkey4)
|
|
|
|
// Publish it
|
|
|
|
notaryPublish(t, notaryDir, homeDir, baseRef)
|
|
|
|
|
|
|
|
// Tag & push with content trust
|
|
|
|
icmd.RunCommand("docker", "pull", fixtures.AlpineImage).Assert(t, icmd.Success)
|
|
|
|
icmd.RunCommand("docker", "tag", fixtures.AlpineImage, targetRef).Assert(t, icmd.Success)
|
|
|
|
result := icmd.RunCmd(icmd.Command("docker", "push", targetRef),
|
|
|
|
fixtures.WithConfig(dir.Path()),
|
|
|
|
fixtures.WithTrust,
|
|
|
|
fixtures.WithNotary,
|
|
|
|
fixtures.WithPassphrase("foo", "foo"),
|
|
|
|
)
|
|
|
|
result.Assert(t, icmd.Expected{
|
|
|
|
Out: "Signing and pushing trust metadata",
|
|
|
|
})
|
|
|
|
|
|
|
|
// check to make sure that the target has been added to targets/role1 and targets/role4, and
|
|
|
|
// not targets (because there are delegations) or targets/role2 (due to path restrictions) or
|
|
|
|
// targets/role3 (due to missing key)
|
|
|
|
targetsInRole := notaryListTargetsInRole(t, notaryDir, homeDir, baseRef, "targets/role1")
|
|
|
|
assert.Assert(t, targetsInRole["latest"] == "targets/role1", "%v", targetsInRole)
|
|
|
|
targetsInRole = notaryListTargetsInRole(t, notaryDir, homeDir, baseRef, "targets/role4")
|
|
|
|
assert.Assert(t, targetsInRole["latest"] == "targets/role4", "%v", targetsInRole)
|
|
|
|
targetsInRole = notaryListTargetsInRole(t, notaryDir, homeDir, baseRef, "targets")
|
|
|
|
assert.Assert(t, targetsInRole["latest"] != "targets", "%v", targetsInRole)
|
|
|
|
|
linting: address assorted issues found by gocritic
internal/test/builders/config.go:36:15: captLocal: `ID' should not be capitalized (gocritic)
func ConfigID(ID string) func(config *swarm.Config) {
^
internal/test/builders/secret.go:45:15: captLocal: `ID' should not be capitalized (gocritic)
func SecretID(ID string) func(secret *swarm.Secret) {
^
internal/test/builders/service.go:21:16: captLocal: `ID' should not be capitalized (gocritic)
func ServiceID(ID string) func(*swarm.Service) {
^
cli/command/image/formatter_history.go:100:15: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(c.h.CreatedBy, "\t", " ", -1)` (gocritic)
createdBy := strings.Replace(c.h.CreatedBy, "\t", " ", -1)
^
e2e/image/push_test.go:246:34: badCall: suspicious Join on 1 argument (gocritic)
assert.NilError(t, os.RemoveAll(filepath.Join(dir.Join("trust"))))
^
e2e/image/push_test.go:313:34: badCall: suspicious Join on 1 argument (gocritic)
assert.NilError(t, os.RemoveAll(filepath.Join(dir.Join("trust"))))
^
cli/config/configfile/file_test.go:185:2: assignOp: replace `c.GetAllCallCount = c.GetAllCallCount + 1` with `c.GetAllCallCount++` (gocritic)
c.GetAllCallCount = c.GetAllCallCount + 1
^
cli/command/context/inspect_test.go:20:58: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(si.MetadataPath, `\`, `\\`, -1)` (gocritic)
expected = strings.Replace(expected, "<METADATA_PATH>", strings.Replace(si.MetadataPath, `\`, `\\`, -1), 1)
^
cli/command/context/inspect_test.go:21:53: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(si.TLSPath, `\`, `\\`, -1)` (gocritic)
expected = strings.Replace(expected, "<TLS_PATH>", strings.Replace(si.TLSPath, `\`, `\\`, -1), 1)
^
cli/command/container/formatter_stats.go:119:46: captLocal: `Stats' should not be capitalized (gocritic)
func statsFormatWrite(ctx formatter.Context, Stats []StatsEntry, osType string, trunc bool) error {
^
cli/command/container/stats_helpers.go:209:4: assignOp: replace `blkRead = blkRead + bioEntry.Value` with `blkRead += bioEntry.Value` (gocritic)
blkRead = blkRead + bioEntry.Value
^
cli/command/container/stats_helpers.go:211:4: assignOp: replace `blkWrite = blkWrite + bioEntry.Value` with `blkWrite += bioEntry.Value` (gocritic)
blkWrite = blkWrite + bioEntry.Value
^
cli/command/registry/formatter_search.go:67:10: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(c.s.Description, "\n", " ", -1)` (gocritic)
desc := strings.Replace(c.s.Description, "\n", " ", -1)
^
cli/command/registry/formatter_search.go:68:9: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(desc, "\r", " ", -1)` (gocritic)
desc = strings.Replace(desc, "\r", " ", -1)
^
cli/command/service/list_test.go:164:5: assignOp: replace `tc.doc = tc.doc + " with quiet"` with `tc.doc += " with quiet"` (gocritic)
tc.doc = tc.doc + " with quiet"
^
cli/command/service/progress/progress.go:274:11: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(errMsg, "\n", " ", -1)` (gocritic)
errMsg = strings.Replace(errMsg, "\n", " ", -1)
^
cli/manifest/store/store.go:153:9: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(fileName, "/", "_", -1)` (gocritic)
return strings.Replace(fileName, "/", "_", -1)
^
cli/manifest/store/store.go:152:14: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(ref, ":", "-", -1)` (gocritic)
fileName := strings.Replace(ref, ":", "-", -1)
^
cli/command/plugin/formatter.go:79:10: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(c.p.Config.Description, "\n", "", -1)` (gocritic)
desc := strings.Replace(c.p.Config.Description, "\n", "", -1)
^
cli/command/plugin/formatter.go:80:9: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(desc, "\r", "", -1)` (gocritic)
desc = strings.Replace(desc, "\r", "", -1)
^
cli/compose/convert/service.go:642:23: captLocal: `DNS' should not be capitalized (gocritic)
func convertDNSConfig(DNS []string, DNSSearch []string) *swarm.DNSConfig {
^
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-11-20 07:30:05 -05:00
|
|
|
assert.NilError(t, os.RemoveAll(dir.Join("trust")))
|
2018-03-06 05:15:18 -05:00
|
|
|
// Try to pull, should fail because non of these are the release role
|
|
|
|
// FIXME(vdemeester) should be unit test
|
|
|
|
result = icmd.RunCmd(icmd.Command("docker", "pull", targetRef),
|
|
|
|
fixtures.WithConfig(dir.Path()),
|
|
|
|
fixtures.WithTrust,
|
|
|
|
fixtures.WithNotary,
|
|
|
|
)
|
|
|
|
result.Assert(t, icmd.Expected{
|
|
|
|
ExitCode: 1,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
implement docker push -a/--all-tags
The `docker push` command up until [v0.9.1](https://github.com/moby/moby/blob/v0.9.1/api/client.go#L998)
always pushed all tags of a given image, so `docker push foo/bar` would push (e.g.)
all of `foo/bar:latest`, `foo:/bar:v1`, `foo/bar:v1.0.0`.
Pushing all tags of an image was not desirable in many case, so docker v0.10.0
enhanced `docker push` to optionally specify a tag to push (`docker push foo/bar:v1`)
(see https://github.com/moby/moby/issues/3411 and the pull request that implemented
this: https://github.com/moby/moby/pull/4948).
This behavior exists up until today, and is confusing, because unlike other commands,
`docker push` does not default to use the `:latest` tag when omitted, but instead
makes it push "all tags of the image"
For example, in the following situation;
```
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thajeztah/myimage latest b534869c81f0 41 hours ago 1.22MB
```
Running `docker push thajeztah/myimage` seemingly does the expected behavior (it
pushes `thajeztah/myimage:latest` to Docker Hub), however, it does not so for the
reason expected (`:latest` being the default tag), but because `:latest` happens
to be the only tag present for the `thajeztah/myimage` image.
If another tag exists for the image:
```
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thajeztah/myimage latest b534869c81f0 41 hours ago 1.22MB
thajeztah/myimage v1.0.0 b534869c81f0 41 hours ago 1.22MB
```
Running the same command (`docker push thajeztah/myimage`) will push _both_ images
to Docker Hub.
> Note that the behavior described above is currently not (clearly) documented;
> the `docker push` reference documentation (https://docs.docker.com/engine/reference/commandline/push/)
does not mention that omitting the tag will push all tags
This patch changes the default behavior, and if no tag is specified, `:latest` is
assumed. To push _all_ tags, a new flag (`-a` / `--all-tags`) is added, similar
to the flag that's present on `docker pull`.
With this change:
- `docker push myname/myimage` will be the equivalent of `docker push myname/myimage:latest`
- to push all images, the user needs to set a flag (`--all-tags`), so `docker push --all-tags myname/myimage:latest`
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-12-09 08:48:42 -05:00
|
|
|
func createImage(t *testing.T, repo string, tags ...string) string {
|
2023-11-20 05:10:29 -05:00
|
|
|
t.Helper()
|
2018-03-06 05:15:18 -05:00
|
|
|
icmd.RunCommand("docker", "pull", fixtures.AlpineImage).Assert(t, icmd.Success)
|
implement docker push -a/--all-tags
The `docker push` command up until [v0.9.1](https://github.com/moby/moby/blob/v0.9.1/api/client.go#L998)
always pushed all tags of a given image, so `docker push foo/bar` would push (e.g.)
all of `foo/bar:latest`, `foo:/bar:v1`, `foo/bar:v1.0.0`.
Pushing all tags of an image was not desirable in many case, so docker v0.10.0
enhanced `docker push` to optionally specify a tag to push (`docker push foo/bar:v1`)
(see https://github.com/moby/moby/issues/3411 and the pull request that implemented
this: https://github.com/moby/moby/pull/4948).
This behavior exists up until today, and is confusing, because unlike other commands,
`docker push` does not default to use the `:latest` tag when omitted, but instead
makes it push "all tags of the image"
For example, in the following situation;
```
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thajeztah/myimage latest b534869c81f0 41 hours ago 1.22MB
```
Running `docker push thajeztah/myimage` seemingly does the expected behavior (it
pushes `thajeztah/myimage:latest` to Docker Hub), however, it does not so for the
reason expected (`:latest` being the default tag), but because `:latest` happens
to be the only tag present for the `thajeztah/myimage` image.
If another tag exists for the image:
```
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thajeztah/myimage latest b534869c81f0 41 hours ago 1.22MB
thajeztah/myimage v1.0.0 b534869c81f0 41 hours ago 1.22MB
```
Running the same command (`docker push thajeztah/myimage`) will push _both_ images
to Docker Hub.
> Note that the behavior described above is currently not (clearly) documented;
> the `docker push` reference documentation (https://docs.docker.com/engine/reference/commandline/push/)
does not mention that omitting the tag will push all tags
This patch changes the default behavior, and if no tag is specified, `:latest` is
assumed. To push _all_ tags, a new flag (`-a` / `--all-tags`) is added, similar
to the flag that's present on `docker pull`.
With this change:
- `docker push myname/myimage` will be the equivalent of `docker push myname/myimage:latest`
- to push all images, the user needs to set a flag (`--all-tags`), so `docker push --all-tags myname/myimage:latest`
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-12-09 08:48:42 -05:00
|
|
|
|
|
|
|
for _, tag := range tags {
|
|
|
|
image := fmt.Sprintf("%s/%s:%s", registryPrefix, repo, tag)
|
|
|
|
icmd.RunCommand("docker", "tag", fixtures.AlpineImage, image).Assert(t, icmd.Success)
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("%s/%s:%s", registryPrefix, repo, tags[0])
|
2018-03-06 05:15:18 -05:00
|
|
|
}
|
|
|
|
|
2022-07-13 06:29:49 -04:00
|
|
|
//nolint:unparam
|
2018-03-06 05:15:18 -05:00
|
|
|
func withNotaryPassphrase(pwd string) func(*icmd.Cmd) {
|
|
|
|
return func(c *icmd.Cmd) {
|
|
|
|
c.Env = append(c.Env, []string{
|
linting: fmt.Sprintf can be replaced with string concatenation (perfsprint)
cli/registry/client/endpoint.go:128:34: fmt.Sprintf can be replaced with string concatenation (perfsprint)
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", th.token))
^
cli/command/telemetry_docker.go:88:14: fmt.Sprintf can be replaced with string concatenation (perfsprint)
endpoint = fmt.Sprintf("unix://%s", path.Join(u.Host, u.Path))
^
cli/command/cli_test.go:195:47: fmt.Sprintf can be replaced with string concatenation (perfsprint)
opts := &flags.ClientOptions{Hosts: []string{fmt.Sprintf("unix://%s", socket)}}
^
cli/command/registry_test.go:59:24: fmt.Sprintf can be replaced with string concatenation (perfsprint)
inputServerAddress: fmt.Sprintf("https://%s", testAuthConfigs[1].ServerAddress),
^
cli/command/container/opts_test.go:338:35: fmt.Sprintf can be replaced with string concatenation (perfsprint)
if config, _, _ := mustParse(t, fmt.Sprintf("--hostname=%s", hostname)); config.Hostname != expectedHostname {
^
cli/command/context/options.go:79:24: fmt.Sprintf can be replaced with string concatenation (perfsprint)
errs = append(errs, fmt.Sprintf("%s: unrecognized config key", k))
^
cli/command/image/build.go:461:68: fmt.Sprintf can be replaced with string concatenation (perfsprint)
line = dockerfileFromLinePattern.ReplaceAllLiteralString(line, fmt.Sprintf("FROM %s", reference.FamiliarString(trustedRef)))
^
cli/command/image/remove_test.go:21:9: fmt.Sprintf can be replaced with string concatenation (perfsprint)
return fmt.Sprintf("Error: No such image: %s", n.imageID)
^
cli/command/image/build/context.go:229:102: fmt.Sprintf can be replaced with string concatenation (perfsprint)
progReader := progress.NewProgressReader(response.Body, progressOutput, response.ContentLength, "", fmt.Sprintf("Downloading build context from remote url: %s", remoteURL))
^
cli/command/service/logs.go:215:16: fmt.Sprintf can be replaced with string concatenation (perfsprint)
taskName += fmt.Sprintf(".%s", task.ID)
^
cli/command/service/logs.go:217:16: fmt.Sprintf can be replaced with string concatenation (perfsprint)
taskName += fmt.Sprintf(".%s", stringid.TruncateID(task.ID))
^
cli/command/service/progress/progress_test.go:877:18: fmt.Sprintf can be replaced with string concatenation (perfsprint)
ID: fmt.Sprintf("task%s", nodeID),
^
cli/command/stack/swarm/remove.go:61:24: fmt.Sprintf can be replaced with string concatenation (perfsprint)
errs = append(errs, fmt.Sprintf("Failed to remove some resources from stack: %s", namespace))
^
cli/command/swarm/ipnet_slice_test.go:32:9: fmt.Sprintf can be replaced with string concatenation (perfsprint)
arg := fmt.Sprintf("--cidrs=%s", strings.Join(vals, ","))
^
cli/command/swarm/ipnet_slice_test.go:137:30: fmt.Sprintf can be replaced with string concatenation (perfsprint)
if err := f.Parse([]string{fmt.Sprintf("--cidrs=%s", strings.Join(test.FlagArg, ","))}); err != nil {
^
cli/compose/schema/schema.go:105:11: fmt.Sprintf can be replaced with string concatenation (perfsprint)
return fmt.Sprintf("must be a %s", humanReadableType(expectedType))
^
cli/manifest/store/store.go:165:9: fmt.Sprintf can be replaced with string concatenation (perfsprint)
return fmt.Sprintf("No such manifest: %s", n.object)
^
e2e/image/push_test.go:340:4: fmt.Sprintf can be replaced with string concatenation (perfsprint)
fmt.Sprintf("NOTARY_ROOT_PASSPHRASE=%s", pwd),
^
e2e/image/push_test.go:341:4: fmt.Sprintf can be replaced with string concatenation (perfsprint)
fmt.Sprintf("NOTARY_TARGETS_PASSPHRASE=%s", pwd),
^
e2e/image/push_test.go:342:4: fmt.Sprintf can be replaced with string concatenation (perfsprint)
fmt.Sprintf("NOTARY_SNAPSHOT_PASSPHRASE=%s", pwd),
^
e2e/image/push_test.go:343:4: fmt.Sprintf can be replaced with string concatenation (perfsprint)
fmt.Sprintf("NOTARY_DELEGATION_PASSPHRASE=%s", pwd),
^
e2e/plugin/trust_test.go:23:16: fmt.Sprintf can be replaced with string concatenation (perfsprint)
pluginName := fmt.Sprintf("%s/plugin-content-trust", registryPrefix)
^
e2e/plugin/trust_test.go:53:8: fmt.Sprintf can be replaced with string concatenation (perfsprint)
Out: fmt.Sprintf("Installed plugin %s", pluginName),
^
e2e/trust/revoke_test.go:62:57: fmt.Sprintf can be replaced with string concatenation (perfsprint)
icmd.RunCommand("docker", "tag", fixtures.AlpineImage, fmt.Sprintf("%s:v1", revokeRepo)).Assert(t, icmd.Success)
^
e2e/trust/revoke_test.go:64:49: fmt.Sprintf can be replaced with string concatenation (perfsprint)
icmd.Command("docker", "-D", "trust", "sign", fmt.Sprintf("%s:v1", revokeRepo)),
^
e2e/trust/revoke_test.go:68:58: fmt.Sprintf can be replaced with string concatenation (perfsprint)
icmd.RunCommand("docker", "tag", fixtures.BusyboxImage, fmt.Sprintf("%s:v2", revokeRepo)).Assert(t, icmd.Success)
^
e2e/trust/revoke_test.go:70:49: fmt.Sprintf can be replaced with string concatenation (perfsprint)
icmd.Command("docker", "-D", "trust", "sign", fmt.Sprintf("%s:v2", revokeRepo)),
^
e2e/trust/sign_test.go:36:47: fmt.Sprintf can be replaced with string concatenation (perfsprint)
assert.Check(t, is.Contains(result.Stdout(), fmt.Sprintf("v1: digest: sha256:%s", fixtures.AlpineSha)))
^
e2e/trust/sign_test.go:53:47: fmt.Sprintf can be replaced with string concatenation (perfsprint)
assert.Check(t, is.Contains(result.Stdout(), fmt.Sprintf("v1: digest: sha256:%s", fixtures.BusyboxSha)))
^
e2e/trust/sign_test.go:65:47: fmt.Sprintf can be replaced with string concatenation (perfsprint)
assert.Check(t, is.Contains(result.Stdout(), fmt.Sprintf("v1: digest: sha256:%s", fixtures.AlpineSha)))
^
opts/file.go:21:9: fmt.Sprintf can be replaced with string concatenation (perfsprint)
return fmt.Sprintf("poorly formatted environment: %s", e.msg)
^
opts/hosts_test.go:26:31: fmt.Sprintf can be replaced with string concatenation (perfsprint)
"tcp://host:": fmt.Sprintf("tcp://host:%s", defaultHTTPPort),
^
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-10 15:07:37 -04:00
|
|
|
"NOTARY_ROOT_PASSPHRASE=" + pwd,
|
|
|
|
"NOTARY_TARGETS_PASSPHRASE=" + pwd,
|
|
|
|
"NOTARY_SNAPSHOT_PASSPHRASE=" + pwd,
|
|
|
|
"NOTARY_DELEGATION_PASSPHRASE=" + pwd,
|
2018-03-06 05:15:18 -05:00
|
|
|
}...)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func notaryImportPrivateKey(t *testing.T, notaryDir, homeDir *fs.Dir, baseRef, role, privkey string) {
|
2023-11-20 05:10:29 -05:00
|
|
|
t.Helper()
|
2018-03-06 05:15:18 -05:00
|
|
|
icmd.RunCmd(
|
|
|
|
icmd.Command(notary, "-c", notaryDir.Join("client-config.json"), "key", "import", privkey, "-g", baseRef, "-r", role),
|
|
|
|
withNotaryPassphrase("foo"),
|
|
|
|
fixtures.WithHome(homeDir.Path()),
|
|
|
|
).Assert(t, icmd.Success)
|
|
|
|
}
|
|
|
|
|
|
|
|
func notaryPublish(t *testing.T, notaryDir, homeDir *fs.Dir, baseRef string) {
|
2023-11-20 05:10:29 -05:00
|
|
|
t.Helper()
|
2018-03-06 05:15:18 -05:00
|
|
|
icmd.RunCmd(
|
|
|
|
icmd.Command(notary, "-c", notaryDir.Join("client-config.json"), "publish", baseRef),
|
|
|
|
withNotaryPassphrase("foo"),
|
|
|
|
fixtures.WithHome(homeDir.Path()),
|
|
|
|
).Assert(t, icmd.Success)
|
|
|
|
}
|
|
|
|
|
|
|
|
func notaryAddDelegation(t *testing.T, notaryDir, homeDir *fs.Dir, baseRef, role, pubkey string, paths ...string) {
|
2023-11-20 05:10:29 -05:00
|
|
|
t.Helper()
|
2018-03-06 05:15:18 -05:00
|
|
|
pathsArg := "--all-paths"
|
|
|
|
if len(paths) > 0 {
|
|
|
|
pathsArg = "--paths=" + strings.Join(paths, ",")
|
|
|
|
}
|
|
|
|
icmd.RunCmd(
|
|
|
|
icmd.Command(notary, "-c", notaryDir.Join("client-config.json"), "delegation", "add", baseRef, role, pubkey, pathsArg),
|
|
|
|
withNotaryPassphrase("foo"),
|
|
|
|
fixtures.WithHome(homeDir.Path()),
|
|
|
|
).Assert(t, icmd.Success)
|
|
|
|
}
|
|
|
|
|
|
|
|
func notaryInit(t *testing.T, notaryDir, homeDir *fs.Dir, baseRef string) {
|
2023-11-20 05:10:29 -05:00
|
|
|
t.Helper()
|
2018-03-06 05:15:18 -05:00
|
|
|
icmd.RunCmd(
|
|
|
|
icmd.Command(notary, "-c", notaryDir.Join("client-config.json"), "init", baseRef),
|
|
|
|
withNotaryPassphrase("foo"),
|
|
|
|
fixtures.WithHome(homeDir.Path()),
|
|
|
|
).Assert(t, icmd.Success)
|
|
|
|
}
|
|
|
|
|
|
|
|
func notaryListTargetsInRole(t *testing.T, notaryDir, homeDir *fs.Dir, baseRef, role string) map[string]string {
|
2023-11-20 05:10:29 -05:00
|
|
|
t.Helper()
|
2018-03-06 05:15:18 -05:00
|
|
|
result := icmd.RunCmd(
|
|
|
|
icmd.Command(notary, "-c", notaryDir.Join("client-config.json"), "list", baseRef, "-r", role),
|
|
|
|
fixtures.WithHome(homeDir.Path()),
|
|
|
|
)
|
|
|
|
out := result.Combined()
|
|
|
|
|
|
|
|
// should look something like:
|
|
|
|
// NAME DIGEST SIZE (BYTES) ROLE
|
|
|
|
// ------------------------------------------------------------------------------------------------------
|
|
|
|
// latest 24a36bbc059b1345b7e8be0df20f1b23caa3602e85d42fff7ecd9d0bd255de56 1377 targets
|
|
|
|
|
|
|
|
targets := make(map[string]string)
|
|
|
|
|
|
|
|
// no target
|
|
|
|
lines := strings.Split(strings.TrimSpace(out), "\n")
|
|
|
|
if len(lines) == 1 && strings.Contains(out, "No targets present in this repository.") {
|
|
|
|
return targets
|
|
|
|
}
|
|
|
|
|
|
|
|
// otherwise, there is at least one target
|
|
|
|
assert.Assert(t, len(lines) >= 3, "output is %s", out)
|
|
|
|
|
|
|
|
for _, line := range lines[2:] {
|
|
|
|
tokens := strings.Fields(line)
|
|
|
|
assert.Assert(t, len(tokens) == 4)
|
|
|
|
targets[tokens[0]] = tokens[3]
|
|
|
|
}
|
|
|
|
|
|
|
|
return targets
|
|
|
|
}
|
|
|
|
|
|
|
|
func setupNotaryConfig(t *testing.T, dockerConfigDir fs.Dir) *fs.Dir {
|
2023-11-20 05:10:29 -05:00
|
|
|
t.Helper()
|
2022-09-30 13:13:22 -04:00
|
|
|
return fs.NewDir(t, "notary_test", fs.WithMode(0o700),
|
2018-03-06 05:15:18 -05:00
|
|
|
fs.WithFile("client-config.json", fmt.Sprintf(`
|
|
|
|
{
|
|
|
|
"trust_dir": "%s",
|
|
|
|
"remote_server": {
|
|
|
|
"url": "%s"
|
|
|
|
}
|
|
|
|
}`, dockerConfigDir.Join("trust"), fixtures.NotaryURL)),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func copyPrivateKey(t *testing.T, dir, source string) {
|
2023-11-20 05:10:29 -05:00
|
|
|
t.Helper()
|
2018-03-06 05:15:18 -05:00
|
|
|
icmd.RunCommand("/bin/cp", source, dir).Assert(t, icmd.Success)
|
|
|
|
}
|