mirror of
https://github.com/moby/moby.git
synced 2026-01-14 17:36:01 +00:00
Compare commits
56 Commits
master
...
v17.06.0-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c5bb024df | ||
|
|
cc547fdd4b | ||
|
|
5c27bce649 | ||
|
|
14bc03dbb8 | ||
|
|
b055794618 | ||
|
|
a65742e314 | ||
|
|
9a727acc15 | ||
|
|
82e1487e72 | ||
|
|
a11bca5891 | ||
|
|
a67f442586 | ||
|
|
842c51c394 | ||
|
|
a2f65ec4aa | ||
|
|
dcbaad5448 | ||
|
|
5c0be74bb8 | ||
|
|
91c49beea0 | ||
|
|
9778382f97 | ||
|
|
70d059f024 | ||
|
|
ab046e94d5 | ||
|
|
5c5ac7eb9b | ||
|
|
d62ed5f3ac | ||
|
|
182cd939be | ||
|
|
f7feb663b7 | ||
|
|
a2b498e128 | ||
|
|
f024e2d7eb | ||
|
|
4e8af4c431 | ||
|
|
e0ffd247bf | ||
|
|
33af086a0b | ||
|
|
3c9dfed30e | ||
|
|
ee9a857558 | ||
|
|
9ab2df07fd | ||
|
|
752471c92f | ||
|
|
f8ecde191a | ||
|
|
093c31c694 | ||
|
|
5c6a466a84 | ||
|
|
4d988e9141 | ||
|
|
b214658e4c | ||
|
|
f981cf94d0 | ||
|
|
b9863603cd | ||
|
|
0f09cebc65 | ||
|
|
870d659101 | ||
|
|
5ee88ddc0d | ||
|
|
631cf6dc8d | ||
|
|
bd04a75392 | ||
|
|
7a11613e94 | ||
|
|
0570feee3d | ||
|
|
daef057517 | ||
|
|
400454cf9a | ||
|
|
b66b1849e9 | ||
|
|
b01ed8895c | ||
|
|
4a5fa1e147 | ||
|
|
393ea2d964 | ||
|
|
90fd450182 | ||
|
|
80cc4bc95f | ||
|
|
9a3a4c0243 | ||
|
|
312781c2e1 | ||
|
|
0aefd9b0f8 |
86
CHANGELOG.md
86
CHANGELOG.md
@@ -5,6 +5,92 @@ information on the list of deprecated flags and APIs please have a look at
|
||||
https://docs.docker.com/engine/deprecated/ where target removal dates can also
|
||||
be found.
|
||||
|
||||
## 17.05.0-ce (2017-05-04)
|
||||
|
||||
### Builder
|
||||
|
||||
+ Add multi-stage build support [#31257](https://github.com/docker/docker/pull/31257) [#32063](https://github.com/docker/docker/pull/32063)
|
||||
+ Allow using build-time args (`ARG`) in `FROM` [#31352](https://github.com/docker/docker/pull/31352)
|
||||
+ Add an option for specifying build target [#32496](https://github.com/docker/docker/pull/32496)
|
||||
* Accept `-f -` to read Dockerfile from `stdin`, but use local context for building [#31236](https://github.com/docker/docker/pull/31236)
|
||||
* The values of default build time arguments (e.g `HTTP_PROXY`) are no longer displayed in docker image history unless a corresponding `ARG` instruction is written in the Dockerfile. [#31584](https://github.com/docker/docker/pull/31584)
|
||||
- Fix setting command if a custom shell is used in a parent image [#32236](https://github.com/docker/docker/pull/32236)
|
||||
- Fix `docker build --label` when the label includes single quotes and a space [#31750](https://github.com/docker/docker/pull/31750)
|
||||
|
||||
### Client
|
||||
|
||||
* Add `--mount` flag to `docker run` and `docker create` [#32251](https://github.com/docker/docker/pull/32251)
|
||||
* Add `--type=secret` to `docker inspect` [#32124](https://github.com/docker/docker/pull/32124)
|
||||
* Add `--format` option to `docker secret ls` [#31552](https://github.com/docker/docker/pull/31552)
|
||||
* Add `--filter` option to `docker secret ls` [#30810](https://github.com/docker/docker/pull/30810)
|
||||
* Add `--filter scope=<swarm|local>` to `docker network ls` [#31529](https://github.com/docker/docker/pull/31529)
|
||||
* Add `--cpus` support to `docker update` [#31148](https://github.com/docker/docker/pull/31148)
|
||||
* Add label filter to `docker system prune` and other `prune` commands [#30740](https://github.com/docker/docker/pull/30740)
|
||||
* `docker stack rm` now accepts multiple stacks as input [#32110](https://github.com/docker/docker/pull/32110)
|
||||
* Improve `docker version --format` option when the client has downgraded the API version [#31022](https://github.com/docker/docker/pull/31022)
|
||||
* Prompt when using an encrypted client certificate to connect to a docker daemon [#31364](https://github.com/docker/docker/pull/31364)
|
||||
* Display created tags on successful `docker build` [#32077](https://github.com/docker/docker/pull/32077)
|
||||
* Cleanup compose convert error messages [#32087](https://github.com/moby/moby/pull/32087)
|
||||
|
||||
### Contrib
|
||||
|
||||
+ Add support for building docker debs for Ubuntu 17.04 Zesty on amd64 [#32435](https://github.com/docker/docker/pull/32435)
|
||||
|
||||
### Daemon
|
||||
|
||||
- Fix `--api-cors-header` being ignored if `--api-enable-cors` is not set [#32174](https://github.com/docker/docker/pull/32174)
|
||||
- Cleanup docker tmp dir on start [#31741](https://github.com/docker/docker/pull/31741)
|
||||
- Deprecate `--graph` flag in favor or `--data-root` [#28696](https://github.com/docker/docker/pull/28696)
|
||||
|
||||
### Logging
|
||||
|
||||
+ Add support for logging driver plugins [#28403](https://github.com/docker/docker/pull/28403)
|
||||
* Add support for showing logs of individual tasks to `docker service logs`, and add `/task/{id}/logs` REST endpoint [#32015](https://github.com/docker/docker/pull/32015)
|
||||
* Add `--log-opt env-regex` option to match environment variables using a regular expression [#27565](https://github.com/docker/docker/pull/27565)
|
||||
|
||||
### Networking
|
||||
|
||||
+ Allow user to replace, and customize the ingress network [#31714](https://github.com/docker/docker/pull/31714)
|
||||
- Fix UDP traffic in containers not working after the container is restarted [#32505](https://github.com/docker/docker/pull/32505)
|
||||
- Fix files being written to `/var/lib/docker` if a different data-root is set [#32505](https://github.com/docker/docker/pull/32505)
|
||||
|
||||
### Runtime
|
||||
|
||||
- Ensure health probe is stopped when a container exits [#32274](https://github.com/docker/docker/pull/32274)
|
||||
|
||||
### Swarm Mode
|
||||
|
||||
+ Add update/rollback order for services (`--update-order` / `--rollback-order`) [#30261](https://github.com/docker/docker/pull/30261)
|
||||
+ Add support for synchronous `service create` and `service update` [#31144](https://github.com/docker/docker/pull/31144)
|
||||
+ Add support for "grace periods" on healthchecks through the `HEALTHCHECK --start-period` and `--health-start-period` flag to
|
||||
`docker service create`, `docker service update`, `docker create`, and `docker run` to support containers with an initial startup
|
||||
time [#28938](https://github.com/docker/docker/pull/28938)
|
||||
* `docker service create` now omits fields that are not specified by the user, when possible. This will allow defaults to be applied inside the manager [#32284](https://github.com/docker/docker/pull/32284)
|
||||
* `docker service inspect` now shows default values for fields that are not specified by the user [#32284](https://github.com/docker/docker/pull/32284)
|
||||
* Move `docker service logs` out of experimental [#32462](https://github.com/docker/docker/pull/32462)
|
||||
* Add support for Credential Spec and SELinux to services to the API [#32339](https://github.com/docker/docker/pull/32339)
|
||||
* Add `--entrypoint` flag to `docker service create` and `docker service update` [#29228](https://github.com/docker/docker/pull/29228)
|
||||
* Add `--network-add` and `--network-rm` to `docker service update` [#32062](https://github.com/docker/docker/pull/32062)
|
||||
* Add `--credential-spec` flag to `docker service create` and `docker service update` [#32339](https://github.com/docker/docker/pull/32339)
|
||||
* Add `--filter mode=<global|replicated>` to `docker service ls` [#31538](https://github.com/docker/docker/pull/31538)
|
||||
* Resolve network IDs on the client side, instead of in the daemon when creating services [#32062](https://github.com/docker/docker/pull/32062)
|
||||
* Add `--format` option to `docker node ls` [#30424](https://github.com/docker/docker/pull/30424)
|
||||
* Add `--prune` option to `docker stack deploy` to remove services that are no longer defined in the docker-compose file [#31302](https://github.com/docker/docker/pull/31302)
|
||||
* Add `PORTS` column for `docker service ls` when using `ingress` mode [#30813](https://github.com/docker/docker/pull/30813)
|
||||
- Fix unnescessary re-deploying of tasks when environment-variables are used [#32364](https://github.com/docker/docker/pull/32364)
|
||||
- Fix `docker stack deploy` not supporting `endpoint_mode` when deploying from a docker compose file [#32333](https://github.com/docker/docker/pull/32333)
|
||||
- Proceed with startup if cluster component cannot be created to allow recovering from a broken swarm setup [#31631](https://github.com/docker/docker/pull/31631)
|
||||
|
||||
### Security
|
||||
|
||||
* Allow setting SELinux type or MCS labels when using `--ipc=container:` or `--ipc=host` [#30652](https://github.com/docker/docker/pull/30652)
|
||||
|
||||
|
||||
### Deprecation
|
||||
|
||||
- Deprecate `--api-enable-cors` daemon flag. This flag was marked deprecated in Docker 1.6.0 but not listed in deprecated features [#32352](https://github.com/docker/docker/pull/32352)
|
||||
- Remove Ubuntu 12.04 (Precise Pangolin) as supported platform. Ubuntu 12.04 is EOL, and no longer receives updates [#32520](https://github.com/docker/docker/pull/32520)
|
||||
|
||||
## 17.04.0-ce (2017-04-05)
|
||||
|
||||
### Builder
|
||||
|
||||
@@ -120,7 +120,7 @@ RUN set -x \
|
||||
# IMPORTANT: If the version of Go is updated, the Windows to Linux CI machines
|
||||
# will need updating, to avoid errors. Ping #docker-maintainers on IRC
|
||||
# with a heads-up.
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" \
|
||||
| tar -xzC /usr/local
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ RUN set -x \
|
||||
# bootstrap, so we use golang-go (1.6) as bootstrap to build Go from source code.
|
||||
# We don't use the official ARMv6 released binaries as a GOROOT_BOOTSTRAP, because
|
||||
# not all ARM64 platforms support 32-bit mode. 32-bit mode is optional for ARMv8.
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN mkdir /usr/src/go && curl -fsSL https://golang.org/dl/go${GO_VERSION}.src.tar.gz | tar -v -C /usr/src/go -xz --strip-components=1 \
|
||||
&& cd /usr/src/go/src \
|
||||
&& GOOS=linux GOARCH=arm64 GOROOT_BOOTSTRAP="$(go env GOROOT)" ./make.bash
|
||||
|
||||
@@ -71,7 +71,7 @@ RUN cd /usr/local/lvm2 \
|
||||
# See https://git.fedorahosted.org/cgit/lvm2.git/tree/INSTALL
|
||||
|
||||
# Install Go
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" \
|
||||
| tar -xzC /usr/local
|
||||
ENV PATH /go/bin:/usr/local/go/bin:$PATH
|
||||
|
||||
@@ -95,7 +95,7 @@ RUN set -x \
|
||||
|
||||
# Install Go
|
||||
# NOTE: official ppc64le go binaries weren't available until go 1.6.4 and 1.7.4
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" \
|
||||
| tar -xzC /usr/local
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ RUN cd /usr/local/lvm2 \
|
||||
&& make install_device-mapper
|
||||
# See https://git.fedorahosted.org/cgit/lvm2.git/tree/INSTALL
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-s390x.tar.gz" \
|
||||
| tar -xzC /usr/local
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ RUN set -x \
|
||||
# IMPORTANT: If the version of Go is updated, the Windows to Linux CI machines
|
||||
# will need updating, to avoid errors. Ping #docker-maintainers on IRC
|
||||
# with a heads-up.
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" \
|
||||
| tar -xzC /usr/local
|
||||
ENV PATH /go/bin:/usr/local/go/bin:$PATH
|
||||
|
||||
@@ -161,7 +161,7 @@ SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPref
|
||||
# Environment variable notes:
|
||||
# - GO_VERSION must be consistent with 'Dockerfile' used by Linux.
|
||||
# - FROM_DOCKERFILE is used for detection of building within a container.
|
||||
ENV GO_VERSION=1.8.1 `
|
||||
ENV GO_VERSION=1.8.3 `
|
||||
GIT_VERSION=2.11.1 `
|
||||
GOPATH=C:\go `
|
||||
FROM_DOCKERFILE=1
|
||||
|
||||
@@ -64,7 +64,7 @@ func maskSecretKeys(inp interface{}) {
|
||||
if form, ok := inp.(map[string]interface{}); ok {
|
||||
loop0:
|
||||
for k, v := range form {
|
||||
for _, m := range []string{"password", "secret", "jointoken", "unlockkey"} {
|
||||
for _, m := range []string{"password", "secret", "jointoken", "unlockkey", "signingcakey"} {
|
||||
if strings.EqualFold(m, k) {
|
||||
form[k] = "*****"
|
||||
continue loop0
|
||||
|
||||
@@ -410,6 +410,9 @@ func buildIpamResources(r *types.NetworkResource, nwInfo libnetwork.NetworkInfo)
|
||||
|
||||
if !hasIpv6Conf {
|
||||
for _, ip6Info := range ipv6Info {
|
||||
if ip6Info.IPAMData.Pool == nil {
|
||||
continue
|
||||
}
|
||||
iData := network.IPAMConfig{}
|
||||
iData.Subnet = ip6Info.IPAMData.Pool.String()
|
||||
iData.Gateway = ip6Info.IPAMData.Gateway.String()
|
||||
|
||||
@@ -2174,9 +2174,6 @@ definitions:
|
||||
Runtime:
|
||||
description: "Runtime is the type of runtime specified for the task executor."
|
||||
type: "string"
|
||||
RuntimeData:
|
||||
description: "RuntimeData is the payload sent to be used with the runtime for the executor."
|
||||
type: "array"
|
||||
Networks:
|
||||
type: "array"
|
||||
items:
|
||||
|
||||
@@ -67,9 +67,6 @@ type TaskSpec struct {
|
||||
ForceUpdate uint64
|
||||
|
||||
Runtime RuntimeType `json:",omitempty"`
|
||||
// TODO (ehazlett): this should be removed and instead
|
||||
// use struct tags (proto) for the runtimes
|
||||
RuntimeData []byte `json:",omitempty"`
|
||||
}
|
||||
|
||||
// Resources represents resources (CPU/Memory).
|
||||
|
||||
@@ -281,7 +281,7 @@ func BuildFromConfig(config *container.Config, changes []string) (*container.Con
|
||||
}
|
||||
dispatchState := newDispatchState()
|
||||
dispatchState.runConfig = config
|
||||
return dispatchFromDockerfile(b, dockerfile, dispatchState)
|
||||
return dispatchFromDockerfile(b, dockerfile, dispatchState, nil)
|
||||
}
|
||||
|
||||
func checkDispatchDockerfile(dockerfile *parser.Node) error {
|
||||
@@ -293,7 +293,7 @@ func checkDispatchDockerfile(dockerfile *parser.Node) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func dispatchFromDockerfile(b *Builder, result *parser.Result, dispatchState *dispatchState) (*container.Config, error) {
|
||||
func dispatchFromDockerfile(b *Builder, result *parser.Result, dispatchState *dispatchState, source builder.Source) (*container.Config, error) {
|
||||
shlex := NewShellLex(result.EscapeToken)
|
||||
ast := result.AST
|
||||
total := len(ast.Children)
|
||||
@@ -304,6 +304,7 @@ func dispatchFromDockerfile(b *Builder, result *parser.Result, dispatchState *di
|
||||
stepMsg: formatStep(i, total),
|
||||
node: n,
|
||||
shlex: shlex,
|
||||
source: source,
|
||||
}
|
||||
if _, err := b.dispatch(opts); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -325,7 +325,7 @@ func processOnBuild(req dispatchRequest) error {
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := dispatchFromDockerfile(req.builder, dockerfile, dispatchState); err != nil {
|
||||
if _, err := dispatchFromDockerfile(req.builder, dockerfile, dispatchState, req.source); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,11 +171,9 @@ func (b *Builder) dispatch(options dispatchOptions) (*dispatchState, error) {
|
||||
buildsFailed.WithValues(metricsUnknownInstructionError).Inc()
|
||||
return nil, fmt.Errorf("unknown instruction: %s", upperCasedCmd)
|
||||
}
|
||||
if err := f(newDispatchRequestFromOptions(options, b, args)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
options.state.updateRunConfig()
|
||||
return options.state, nil
|
||||
err = f(newDispatchRequestFromOptions(options, b, args))
|
||||
return options.state, err
|
||||
}
|
||||
|
||||
type dispatchOptions struct {
|
||||
|
||||
@@ -41,6 +41,7 @@ func Detect(config backend.BuildConfig) (remote builder.Source, dockerfile *pars
|
||||
}
|
||||
|
||||
func newArchiveRemote(rc io.ReadCloser, dockerfilePath string) (builder.Source, *parser.Result, error) {
|
||||
defer rc.Close()
|
||||
c, err := MakeTarSumContext(rc)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
||||
@@ -24,14 +24,18 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec,
|
||||
headers["X-Registry-Auth"] = []string{options.EncodedRegistryAuth}
|
||||
}
|
||||
|
||||
// ensure that the image is tagged
|
||||
if taggedImg := imageWithTagString(service.TaskTemplate.ContainerSpec.Image); taggedImg != "" {
|
||||
service.TaskTemplate.ContainerSpec.Image = taggedImg
|
||||
}
|
||||
|
||||
// Contact the registry to retrieve digest and platform information
|
||||
if options.QueryRegistry {
|
||||
distributionInspect, err := cli.DistributionInspect(ctx, service.TaskTemplate.ContainerSpec.Image, options.EncodedRegistryAuth)
|
||||
distErr = err
|
||||
if err == nil {
|
||||
// now pin by digest if the image doesn't already contain a digest
|
||||
img := imageWithDigestString(service.TaskTemplate.ContainerSpec.Image, distributionInspect.Descriptor.Digest)
|
||||
if img != "" {
|
||||
if img := imageWithDigestString(service.TaskTemplate.ContainerSpec.Image, distributionInspect.Descriptor.Digest); img != "" {
|
||||
service.TaskTemplate.ContainerSpec.Image = img
|
||||
}
|
||||
// add platforms that are compatible with the service
|
||||
@@ -55,22 +59,33 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec,
|
||||
}
|
||||
|
||||
// imageWithDigestString takes an image string and a digest, and updates
|
||||
// the image string if it didn't originally contain a digest. It assumes
|
||||
// that the image string is not an image ID
|
||||
// the image string if it didn't originally contain a digest. It returns
|
||||
// an empty string if there are no updates.
|
||||
func imageWithDigestString(image string, dgst digest.Digest) string {
|
||||
ref, err := reference.ParseAnyReference(image)
|
||||
namedRef, err := reference.ParseNormalizedNamed(image)
|
||||
if err == nil {
|
||||
if _, isCanonical := ref.(reference.Canonical); !isCanonical {
|
||||
namedRef, _ := ref.(reference.Named)
|
||||
if _, isCanonical := namedRef.(reference.Canonical); !isCanonical {
|
||||
// ensure that image gets a default tag if none is provided
|
||||
img, err := reference.WithDigest(namedRef, dgst)
|
||||
if err == nil {
|
||||
return img.String()
|
||||
return reference.FamiliarString(img)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// imageWithTagString takes an image string, and returns a tagged image
|
||||
// string, adding a 'latest' tag if one was not provided. It returns an
|
||||
// emptry string if a canonical reference was provided
|
||||
func imageWithTagString(image string) string {
|
||||
namedRef, err := reference.ParseNormalizedNamed(image)
|
||||
if err == nil {
|
||||
return reference.FamiliarString(reference.TagNameOnly(namedRef))
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// updateServicePlatforms updates the Platforms in swarm.Placement to list
|
||||
// all compatible platforms for the service, as found in distributionInspect
|
||||
// and returns a pointer to the new or updated swarm.Placement struct
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/docker/docker/api/types"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
@@ -121,3 +122,92 @@ func TestServiceCreateCompatiblePlatforms(t *testing.T) {
|
||||
t.Fatalf("expected `service_amd64`, got %s", r.ID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServiceCreateDigestPinning(t *testing.T) {
|
||||
dgst := "sha256:c0537ff6a5218ef531ece93d4984efc99bbf3f7497c0a7726c88e2bb7584dc96"
|
||||
dgstAlt := "sha256:37ffbf3f7497c07584dc9637ffbf3f7497c0758c0537ffbf3f7497c0c88e2bb7"
|
||||
serviceCreateImage := ""
|
||||
pinByDigestTests := []struct {
|
||||
img string // input image provided by the user
|
||||
expected string // expected image after digest pinning
|
||||
}{
|
||||
// default registry returns familiar string
|
||||
{"docker.io/library/alpine", "alpine:latest@" + dgst},
|
||||
// provided tag is preserved and digest added
|
||||
{"alpine:edge", "alpine:edge@" + dgst},
|
||||
// image with provided alternative digest remains unchanged
|
||||
{"alpine@" + dgstAlt, "alpine@" + dgstAlt},
|
||||
// image with provided tag and alternative digest remains unchanged
|
||||
{"alpine:edge@" + dgstAlt, "alpine:edge@" + dgstAlt},
|
||||
// image on alternative registry does not result in familiar string
|
||||
{"alternate.registry/library/alpine", "alternate.registry/library/alpine:latest@" + dgst},
|
||||
// unresolvable image does not get a digest
|
||||
{"cannotresolve", "cannotresolve:latest"},
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
||||
if strings.HasPrefix(req.URL.Path, "/services/create") {
|
||||
// reset and set image received by the service create endpoint
|
||||
serviceCreateImage = ""
|
||||
var service swarm.ServiceSpec
|
||||
if err := json.NewDecoder(req.Body).Decode(&service); err != nil {
|
||||
return nil, fmt.Errorf("could not parse service create request")
|
||||
}
|
||||
serviceCreateImage = service.TaskTemplate.ContainerSpec.Image
|
||||
|
||||
b, err := json.Marshal(types.ServiceCreateResponse{
|
||||
ID: "service_id",
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: ioutil.NopCloser(bytes.NewReader(b)),
|
||||
}, nil
|
||||
} else if strings.HasPrefix(req.URL.Path, "/distribution/cannotresolve") {
|
||||
// unresolvable image
|
||||
return nil, fmt.Errorf("cannot resolve image")
|
||||
} else if strings.HasPrefix(req.URL.Path, "/distribution/") {
|
||||
// resolvable images
|
||||
b, err := json.Marshal(registrytypes.DistributionInspect{
|
||||
Descriptor: v1.Descriptor{
|
||||
Digest: digest.Digest(dgst),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: ioutil.NopCloser(bytes.NewReader(b)),
|
||||
}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected URL '%s'", req.URL.Path)
|
||||
}),
|
||||
}
|
||||
|
||||
// run pin by digest tests
|
||||
for _, p := range pinByDigestTests {
|
||||
r, err := client.ServiceCreate(context.Background(), swarm.ServiceSpec{
|
||||
TaskTemplate: swarm.TaskSpec{
|
||||
ContainerSpec: swarm.ContainerSpec{
|
||||
Image: p.img,
|
||||
},
|
||||
},
|
||||
}, types.ServiceCreateOptions{QueryRegistry: true})
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if r.ID != "service_id" {
|
||||
t.Fatalf("expected `service_id`, got %s", r.ID)
|
||||
}
|
||||
|
||||
if p.expected != serviceCreateImage {
|
||||
t.Fatalf("expected image %s, got %s", p.expected, serviceCreateImage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,11 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version
|
||||
|
||||
query.Set("version", strconv.FormatUint(version.Index, 10))
|
||||
|
||||
// ensure that the image is tagged
|
||||
if taggedImg := imageWithTagString(service.TaskTemplate.ContainerSpec.Image); taggedImg != "" {
|
||||
service.TaskTemplate.ContainerSpec.Image = taggedImg
|
||||
}
|
||||
|
||||
// Contact the registry to retrieve digest and platform information
|
||||
// This happens only when the image has changed
|
||||
if options.QueryRegistry {
|
||||
@@ -42,8 +47,7 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version
|
||||
distErr = err
|
||||
if err == nil {
|
||||
// now pin by digest if the image doesn't already contain a digest
|
||||
img := imageWithDigestString(service.TaskTemplate.ContainerSpec.Image, distributionInspect.Descriptor.Digest)
|
||||
if img != "" {
|
||||
if img := imageWithDigestString(service.TaskTemplate.ContainerSpec.Image, distributionInspect.Descriptor.Digest); img != "" {
|
||||
service.TaskTemplate.ContainerSpec.Image = img
|
||||
}
|
||||
// add platforms that are compatible with the service
|
||||
|
||||
@@ -155,6 +155,8 @@ func (cli *DaemonCli) start(opts daemonOptions) (err error) {
|
||||
api := apiserver.New(serverConfig)
|
||||
cli.api = api
|
||||
|
||||
var hosts []string
|
||||
|
||||
for i := 0; i < len(cli.Config.Hosts); i++ {
|
||||
var err error
|
||||
if cli.Config.Hosts[i], err = dopts.ParseHost(cli.Config.TLS, cli.Config.Hosts[i]); err != nil {
|
||||
@@ -186,6 +188,7 @@ func (cli *DaemonCli) start(opts daemonOptions) (err error) {
|
||||
}
|
||||
}
|
||||
logrus.Debugf("Listener created for HTTP on %s (%s)", proto, addr)
|
||||
hosts = append(hosts, protoAddrParts[1])
|
||||
api.Accept(addr, ls...)
|
||||
}
|
||||
|
||||
@@ -213,6 +216,8 @@ func (cli *DaemonCli) start(opts daemonOptions) (err error) {
|
||||
return fmt.Errorf("Error starting daemon: %v", err)
|
||||
}
|
||||
|
||||
d.StoreHosts(hosts)
|
||||
|
||||
// validate after NewDaemon has restored enabled plugins. Dont change order.
|
||||
if err := validateAuthzPlugins(cli.Config.AuthorizationPlugins, pluginStore); err != nil {
|
||||
return fmt.Errorf("Error validating authorization plugin: %v", err)
|
||||
@@ -402,8 +407,12 @@ func loadDaemonCliConfig(opts daemonOptions) (*config.Config, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if conf.V2Only == false {
|
||||
logrus.Warnf(`The "disable-legacy-registry" option is deprecated and wil be removed in Docker v17.12. Interacting with legacy (v1) registries will no longer be supported in Docker v17.12"`)
|
||||
}
|
||||
|
||||
if flags.Changed("graph") {
|
||||
logrus.Warnf(`the "-g / --graph" flag is deprecated. Please use "--data-root" instead`)
|
||||
logrus.Warnf(`The "-g / --graph" flag is deprecated. Please use "--data-root" instead`)
|
||||
}
|
||||
|
||||
// Labels of the docker engine used to allow multiple values associated with the same key.
|
||||
|
||||
@@ -102,7 +102,7 @@ func TestLoadDaemonConfigWithTrueDefaultValuesLeaveDefaults(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLoadDaemonConfigWithLegacyRegistryOptions(t *testing.T) {
|
||||
content := `{"disable-legacy-registry": true}`
|
||||
content := `{"disable-legacy-registry": false}`
|
||||
tempFile := tempfile.NewTempFile(t, "config", content)
|
||||
defer tempFile.Remove()
|
||||
|
||||
@@ -110,5 +110,5 @@ func TestLoadDaemonConfigWithLegacyRegistryOptions(t *testing.T) {
|
||||
loadedConfig, err := loadDaemonCliConfig(opts)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, loadedConfig)
|
||||
assert.True(t, loadedConfig.V2Only)
|
||||
assert.False(t, loadedConfig.V2Only)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/pkg/pools"
|
||||
"github.com/docker/docker/pkg/promise"
|
||||
"github.com/docker/docker/pkg/term"
|
||||
)
|
||||
@@ -86,7 +87,7 @@ func (c *Config) CopyStreams(ctx context.Context, cfg *AttachConfig) chan error
|
||||
if cfg.TTY {
|
||||
_, err = copyEscapable(cfg.CStdin, cfg.Stdin, cfg.DetachKeys)
|
||||
} else {
|
||||
_, err = io.Copy(cfg.CStdin, cfg.Stdin)
|
||||
_, err = pools.Copy(cfg.CStdin, cfg.Stdin)
|
||||
}
|
||||
if err == io.ErrClosedPipe {
|
||||
err = nil
|
||||
@@ -116,7 +117,7 @@ func (c *Config) CopyStreams(ctx context.Context, cfg *AttachConfig) chan error
|
||||
}
|
||||
|
||||
logrus.Debugf("attach: %s: begin", name)
|
||||
_, err := io.Copy(stream, streamPipe)
|
||||
_, err := pools.Copy(stream, streamPipe)
|
||||
if err == io.ErrClosedPipe {
|
||||
err = nil
|
||||
}
|
||||
@@ -174,5 +175,5 @@ func copyEscapable(dst io.Writer, src io.ReadCloser, keys []byte) (written int64
|
||||
pr := term.NewEscapeProxy(src, keys)
|
||||
defer src.Close()
|
||||
|
||||
return io.Copy(dst, pr)
|
||||
return pools.Copy(dst, pr)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ RUN update-alternatives --install /usr/bin/go go /usr/lib/go-1.6/bin/go 100
|
||||
# Install Go
|
||||
# aarch64 doesn't have official go binaries, so use the version of go installed from
|
||||
# the image to build go from source.
|
||||
ENV GO_VERSION 1.7.5
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN mkdir /usr/src/go && curl -fsSL https://golang.org/dl/go${GO_VERSION}.src.tar.gz | tar -v -C /usr/src/go -xz --strip-components=1 \
|
||||
&& cd /usr/src/go/src \
|
||||
&& GOOS=linux GOARCH=arm64 GOROOT_BOOTSTRAP="$(go env GOROOT)" ./make.bash
|
||||
|
||||
@@ -9,7 +9,7 @@ RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools bu
|
||||
# Install Go
|
||||
# aarch64 doesn't have official go binaries, so use the version of go installed from
|
||||
# the image to build go from source.
|
||||
ENV GO_VERSION 1.7.5
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN mkdir /usr/src/go && curl -fsSL https://golang.org/dl/go${GO_VERSION}.src.tar.gz | tar -v -C /usr/src/go -xz --strip-components=1 \
|
||||
&& cd /usr/src/go/src \
|
||||
&& GOOS=linux GOARCH=arm64 GOROOT_BOOTSTRAP="$(go env GOROOT)" ./make.bash
|
||||
|
||||
@@ -11,7 +11,7 @@ RUN update-alternatives --install /usr/bin/go go /usr/lib/go-1.6/bin/go 100
|
||||
# Install Go
|
||||
# aarch64 doesn't have official go binaries, so use the version of go installed from
|
||||
# the image to build go from source.
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN mkdir /usr/src/go && curl -fsSL https://golang.org/dl/go${GO_VERSION}.src.tar.gz | tar -v -C /usr/src/go -xz --strip-components=1 \
|
||||
&& cd /usr/src/go/src \
|
||||
&& GOOS=linux GOARCH=arm64 GOROOT_BOOTSTRAP="$(go env GOROOT)" ./make.bash
|
||||
|
||||
@@ -9,7 +9,7 @@ RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools bu
|
||||
# Install Go
|
||||
# aarch64 doesn't have official go binaries, so use the version of go installed from
|
||||
# the image to build go from source.
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN mkdir /usr/src/go && curl -fsSL https://golang.org/dl/go${GO_VERSION}.src.tar.gz | tar -v -C /usr/src/go -xz --strip-components=1 \
|
||||
&& cd /usr/src/go/src \
|
||||
&& GOOS=linux GOARCH=arm64 GOROOT_BOOTSTRAP="$(go env GOROOT)" ./make.bash
|
||||
|
||||
@@ -10,7 +10,7 @@ RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list.d
|
||||
RUN apt-get update && apt-get install -y -t wheezy-backports btrfs-tools --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM ubuntu:trusty
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM ubuntu:xenial
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM ubuntu:yakkety
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM ubuntu:zesty
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.7.5
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
# GOARM is the ARM architecture version which is unrelated to the above Golang version
|
||||
ENV GOARM 6
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM armhf/ubuntu:trusty
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM armhf/ubuntu:xenial
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM armhf/ubuntu:yakkety
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM ppc64le/ubuntu:trusty
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM ppc64le/ubuntu:xenial
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common libseccomp-dev libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM ppc64le/ubuntu:yakkety
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common libseccomp-dev libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM s390x/ubuntu:xenial
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev pkg-config libsystemd-dev vim-common --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-s390x.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM s390x/ubuntu:yakkety
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev pkg-config libsystemd-dev vim-common --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.7.5
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-s390x.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ FROM amazonlinux:latest
|
||||
RUN yum groupinstall -y "Development Tools"
|
||||
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel tar git cmake vim-common
|
||||
|
||||
ENV GO_VERSION 1.7.5
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ RUN yum groupinstall -y "Development Tools"
|
||||
RUN yum -y swap -- remove systemd-container systemd-container-libs -- install systemd systemd-libs
|
||||
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ RUN dnf -y upgrade
|
||||
RUN dnf install -y @development-tools fedora-packager
|
||||
RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ RUN dnf -y upgrade
|
||||
RUN dnf install -y @development-tools fedora-packager
|
||||
RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ FROM opensuse:13.2
|
||||
RUN zypper --non-interactive install ca-certificates* curl gzip rpm-build
|
||||
RUN zypper --non-interactive install libbtrfs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkg-config selinux-policy selinux-policy-devel systemd-devel tar git cmake vim systemd-rpm-macros
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ RUN yum install -y kernel-uek-devel-4.1.12-32.el6uek
|
||||
RUN yum groupinstall -y "Development Tools"
|
||||
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel tar git cmake vim-common
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ FROM oraclelinux:7
|
||||
RUN yum groupinstall -y "Development Tools"
|
||||
RUN yum install -y --enablerepo=ol7_optional_latest btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ FROM photon:1.0
|
||||
RUN tdnf install -y wget curl ca-certificates gzip make rpm-build sed gcc linux-api-headers glibc-devel binutils libseccomp libltdl-devel elfutils
|
||||
RUN tdnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkg-config selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ RUN yum groupinstall --skip-broken -y "Development Tools"
|
||||
RUN yum -y swap -- remove systemd-container systemd-container-libs -- install systemd systemd-libs
|
||||
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim-common
|
||||
|
||||
ENV GO_VERSION 1.7.4
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ RUN dnf -y upgrade
|
||||
RUN dnf install -y @development-tools fedora-packager
|
||||
RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake
|
||||
|
||||
ENV GO_VERSION 1.8.1
|
||||
ENV GO_VERSION 1.8.3
|
||||
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -2620,7 +2620,7 @@ __docker_subcommand() {
|
||||
"($help)--default-gateway-v6[Container default gateway IPv6 address]:IPv6 address: " \
|
||||
"($help)--default-shm-size=[Default shm size for containers]:size:" \
|
||||
"($help)*--default-ulimit=[Default ulimits for containers]:ulimit: " \
|
||||
"($help)--disable-legacy-registry[Disable contacting legacy registries]" \
|
||||
"($help)--disable-legacy-registry[Disable contacting legacy registries (default true)]" \
|
||||
"($help)*--dns=[DNS server to use]:DNS: " \
|
||||
"($help)*--dns-opt=[DNS options to use]:DNS option: " \
|
||||
"($help)*--dns-search=[DNS search domains to use]:DNS search: " \
|
||||
|
||||
@@ -100,7 +100,6 @@ func serviceSpecFromGRPC(spec *swarmapi.ServiceSpec) (*types.ServiceSpec, error)
|
||||
return nil, fmt.Errorf("unknown task runtime type: %s", t.Generic.Payload.TypeUrl)
|
||||
}
|
||||
|
||||
taskTemplate.RuntimeData = t.Generic.Payload.Value
|
||||
default:
|
||||
return nil, fmt.Errorf("error creating service; unsupported runtime %T", t)
|
||||
}
|
||||
@@ -176,7 +175,6 @@ func ServiceSpecToGRPC(s types.ServiceSpec) (swarmapi.ServiceSpec, error) {
|
||||
Kind: string(types.RuntimePlugin),
|
||||
Payload: &gogotypes.Any{
|
||||
TypeUrl: string(types.RuntimeURLPlugin),
|
||||
Value: s.TaskTemplate.RuntimeData,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -31,9 +31,10 @@ func SwarmFromGRPC(c swarmapi.Cluster) types.Swarm {
|
||||
AutoLockManagers: c.Spec.EncryptionConfig.AutoLockManagers,
|
||||
},
|
||||
CAConfig: types.CAConfig{
|
||||
// do not include the signing CA key (it should already be redacted via the swarm APIs)
|
||||
SigningCACert: string(c.Spec.CAConfig.SigningCACert),
|
||||
ForceRotate: c.Spec.CAConfig.ForceRotate,
|
||||
// do not include the signing CA cert or key (it should already be redacted via the swarm APIs) -
|
||||
// the key because it's secret, and the cert because otherwise doing a get + update on the spec
|
||||
// can cause issues because the key would be missing and the cert wouldn't
|
||||
ForceRotate: c.Spec.CAConfig.ForceRotate,
|
||||
},
|
||||
},
|
||||
TLSInfo: types.TLSInfo{
|
||||
|
||||
@@ -495,7 +495,6 @@ func getEndpointConfig(na *api.NetworkAttachment, b executorpkg.Backend) *networ
|
||||
IPv4Address: ipv4,
|
||||
IPv6Address: ipv6,
|
||||
},
|
||||
Aliases: na.Aliases,
|
||||
DriverOpts: na.DriverAttachmentOpts,
|
||||
}
|
||||
if v, ok := na.Network.Spec.Annotations.Labels["com.docker.swarm.predefined"]; ok && v == "true" {
|
||||
|
||||
@@ -88,10 +88,6 @@ func (c *Cluster) Init(req types.InitRequest) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if !req.ForceNewCluster {
|
||||
clearPersistentState(c.root)
|
||||
}
|
||||
|
||||
nr, err := c.newNodeRunner(nodeStartConfig{
|
||||
forceNewCluster: req.ForceNewCluster,
|
||||
autolock: req.AutoLockManagers,
|
||||
@@ -109,16 +105,14 @@ func (c *Cluster) Init(req types.InitRequest) (string, error) {
|
||||
c.mu.Unlock()
|
||||
|
||||
if err := <-nr.Ready(); err != nil {
|
||||
c.mu.Lock()
|
||||
c.nr = nil
|
||||
c.mu.Unlock()
|
||||
if !req.ForceNewCluster { // if failure on first attempt don't keep state
|
||||
if err := clearPersistentState(c.root); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
c.mu.Lock()
|
||||
c.nr = nil
|
||||
c.mu.Unlock()
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
state := nr.State()
|
||||
@@ -166,8 +160,6 @@ func (c *Cluster) Join(req types.JoinRequest) error {
|
||||
return err
|
||||
}
|
||||
|
||||
clearPersistentState(c.root)
|
||||
|
||||
nr, err := c.newNodeRunner(nodeStartConfig{
|
||||
RemoteAddr: req.RemoteAddrs[0],
|
||||
ListenAddr: net.JoinHostPort(listenHost, listenPort),
|
||||
@@ -193,6 +185,9 @@ func (c *Cluster) Join(req types.JoinRequest) error {
|
||||
c.mu.Lock()
|
||||
c.nr = nil
|
||||
c.mu.Unlock()
|
||||
if err := clearPersistentState(c.root); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -116,6 +116,17 @@ type Daemon struct {
|
||||
|
||||
diskUsageRunning int32
|
||||
pruneRunning int32
|
||||
hosts map[string]bool // hosts stores the addresses the daemon is listening on
|
||||
}
|
||||
|
||||
// StoreHosts stores the addresses the daemon is listening on
|
||||
func (daemon *Daemon) StoreHosts(hosts []string) {
|
||||
if daemon.hosts == nil {
|
||||
daemon.hosts = make(map[string]bool)
|
||||
}
|
||||
for _, h := range hosts {
|
||||
daemon.hosts[h] = true
|
||||
}
|
||||
}
|
||||
|
||||
// HasExperimental returns whether the experimental features of the daemon are enabled or not
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const dataStructuresLogNameTemplate = "daemon-data-%s.log"
|
||||
|
||||
// dumpDaemon appends the daemon datastructures into file in dir and returns full path
|
||||
// to that file.
|
||||
func (d *Daemon) dumpDaemon(dir string) (string, error) {
|
||||
// Ensure we recover from a panic as we are doing this without any locking
|
||||
defer func() {
|
||||
recover()
|
||||
}()
|
||||
|
||||
path := filepath.Join(dir, fmt.Sprintf(dataStructuresLogNameTemplate, strings.Replace(time.Now().Format(time.RFC3339), ":", "", -1)))
|
||||
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to open file to write the daemon datastructure dump")
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
dump := struct {
|
||||
containers interface{}
|
||||
names interface{}
|
||||
links interface{}
|
||||
execs interface{}
|
||||
volumes interface{}
|
||||
images interface{}
|
||||
layers interface{}
|
||||
imageReferences interface{}
|
||||
downloads interface{}
|
||||
uploads interface{}
|
||||
registry interface{}
|
||||
plugins interface{}
|
||||
}{
|
||||
containers: d.containers,
|
||||
execs: d.execCommands,
|
||||
volumes: d.volumes,
|
||||
images: d.imageStore,
|
||||
layers: d.layerStore,
|
||||
imageReferences: d.referenceStore,
|
||||
downloads: d.downloadManager,
|
||||
uploads: d.uploadManager,
|
||||
registry: d.RegistryService,
|
||||
plugins: d.PluginStore,
|
||||
names: d.nameIndex,
|
||||
links: d.linkIndex,
|
||||
}
|
||||
|
||||
spew.Fdump(f, dump) // Does not return an error
|
||||
f.Sync()
|
||||
return path, nil
|
||||
}
|
||||
@@ -22,12 +22,6 @@ func (d *Daemon) setupDumpStackTrap(root string) {
|
||||
} else {
|
||||
logrus.Infof("goroutine stacks written to %s", path)
|
||||
}
|
||||
path, err = d.dumpDaemon(root)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("failed to write daemon datastructure dump")
|
||||
} else {
|
||||
logrus.Infof("daemon datastructure dump written to %s", path)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -41,12 +41,6 @@ func (d *Daemon) setupDumpStackTrap(root string) {
|
||||
} else {
|
||||
logrus.Infof("goroutine stacks written to %s", path)
|
||||
}
|
||||
path, err = d.dumpDaemon(root)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("failed to write daemon datastructure dump")
|
||||
} else {
|
||||
logrus.Infof("daemon datastructure dump written to %s", path)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -64,31 +64,35 @@ type cmdProbe struct {
|
||||
|
||||
// exec the healthcheck command in the container.
|
||||
// Returns the exit code and probe output (if any)
|
||||
func (p *cmdProbe) run(ctx context.Context, d *Daemon, container *container.Container) (*types.HealthcheckResult, error) {
|
||||
|
||||
cmdSlice := strslice.StrSlice(container.Config.Healthcheck.Test)[1:]
|
||||
func (p *cmdProbe) run(ctx context.Context, d *Daemon, cntr *container.Container) (*types.HealthcheckResult, error) {
|
||||
cmdSlice := strslice.StrSlice(cntr.Config.Healthcheck.Test)[1:]
|
||||
if p.shell {
|
||||
cmdSlice = append(getShell(container.Config), cmdSlice...)
|
||||
cmdSlice = append(getShell(cntr.Config), cmdSlice...)
|
||||
}
|
||||
entrypoint, args := d.getEntrypointAndArgs(strslice.StrSlice{}, cmdSlice)
|
||||
execConfig := exec.NewConfig()
|
||||
execConfig.OpenStdin = false
|
||||
execConfig.OpenStdout = true
|
||||
execConfig.OpenStderr = true
|
||||
execConfig.ContainerID = container.ID
|
||||
execConfig.ContainerID = cntr.ID
|
||||
execConfig.DetachKeys = []byte{}
|
||||
execConfig.Entrypoint = entrypoint
|
||||
execConfig.Args = args
|
||||
execConfig.Tty = false
|
||||
execConfig.Privileged = false
|
||||
execConfig.User = container.Config.User
|
||||
execConfig.Env = container.Config.Env
|
||||
execConfig.User = cntr.Config.User
|
||||
|
||||
d.registerExecCommand(container, execConfig)
|
||||
d.LogContainerEvent(container, "exec_create: "+execConfig.Entrypoint+" "+strings.Join(execConfig.Args, " "))
|
||||
linkedEnv, err := d.setupLinkedContainers(cntr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
execConfig.Env = container.ReplaceOrAppendEnvValues(cntr.CreateDaemonEnvironment(execConfig.Tty, linkedEnv), execConfig.Env)
|
||||
|
||||
d.registerExecCommand(cntr, execConfig)
|
||||
d.LogContainerEvent(cntr, "exec_create: "+execConfig.Entrypoint+" "+strings.Join(execConfig.Args, " "))
|
||||
|
||||
output := &limitedBuffer{}
|
||||
err := d.ContainerExecStart(ctx, execConfig.ID, nil, output, output)
|
||||
err = d.ContainerExecStart(ctx, execConfig.ID, nil, output, output)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -97,7 +101,7 @@ func (p *cmdProbe) run(ctx context.Context, d *Daemon, container *container.Cont
|
||||
return nil, err
|
||||
}
|
||||
if info.ExitCode == nil {
|
||||
return nil, fmt.Errorf("Healthcheck for container %s has no exit code!", container.ID)
|
||||
return nil, fmt.Errorf("Healthcheck for container %s has no exit code!", cntr.ID)
|
||||
}
|
||||
// Note: Go's json package will handle invalid UTF-8 for us
|
||||
out := output.String()
|
||||
|
||||
@@ -69,7 +69,7 @@ func (daemon *Daemon) killWithSignal(container *containerpkg.Container, sig int)
|
||||
return errNotRunning{container.ID}
|
||||
}
|
||||
|
||||
if container.Config.StopSignal != "" {
|
||||
if container.Config.StopSignal != "" && syscall.Signal(sig) != syscall.SIGKILL {
|
||||
containerStopSignal, err := signal.ParseSignal(container.Config.StopSignal)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -3,6 +3,7 @@ package logger
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -18,6 +19,7 @@ type pluginAdapter struct {
|
||||
driverName string
|
||||
id string
|
||||
plugin logPlugin
|
||||
basePath string
|
||||
fifoPath string
|
||||
capabilities Capability
|
||||
logInfo Info
|
||||
@@ -56,7 +58,7 @@ func (a *pluginAdapter) Close() error {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
|
||||
if err := a.plugin.StopLogging(a.fifoPath); err != nil {
|
||||
if err := a.plugin.StopLogging(strings.TrimPrefix(a.fifoPath, a.basePath)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ func makePluginCreator(name string, l *logPluginProxy, basePath string) Creator
|
||||
driverName: name,
|
||||
id: id,
|
||||
plugin: l,
|
||||
basePath: basePath,
|
||||
fifoPath: filepath.Join(root, id),
|
||||
logInfo: logCtx,
|
||||
}
|
||||
|
||||
@@ -46,7 +46,8 @@ func (daemon *Daemon) StateChanged(id string, e libcontainerd.StateInfo) error {
|
||||
c.StreamConfig.Wait()
|
||||
c.Reset(false)
|
||||
|
||||
restart, wait, err := c.RestartManager().ShouldRestart(e.ExitCode, c.HasBeenManuallyStopped, time.Since(c.StartedAt))
|
||||
// If daemon is being shutdown, don't let the container restart
|
||||
restart, wait, err := c.RestartManager().ShouldRestart(e.ExitCode, daemon.IsShuttingDown() || c.HasBeenManuallyStopped, time.Since(c.StartedAt))
|
||||
if err == nil && restart {
|
||||
c.RestartCount++
|
||||
c.SetRestarting(platformConstructExitStatus(e))
|
||||
|
||||
@@ -216,7 +216,7 @@ func (daemon *Daemon) ImagesPrune(ctx context.Context, pruneFilters filters.Args
|
||||
if !until.IsZero() && img.Created.After(until) {
|
||||
continue
|
||||
}
|
||||
if !matchLabels(pruneFilters, img.Config.Labels) {
|
||||
if img.Config != nil && !matchLabels(pruneFilters, img.Config.Labels) {
|
||||
continue
|
||||
}
|
||||
topImages[id] = img
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/layer"
|
||||
"github.com/docker/docker/libcontainerd"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
@@ -32,12 +31,6 @@ func (daemon *Daemon) getLibcontainerdCreateOptions(container *container.Contain
|
||||
}
|
||||
|
||||
dnsSearch := daemon.getDNSSearchSettings(container)
|
||||
if dnsSearch != nil {
|
||||
osv := system.GetOSVersion()
|
||||
if osv.Build < 14997 {
|
||||
return nil, fmt.Errorf("dns-search option is not supported on the current platform")
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the layer folder of the layer options
|
||||
layerOpts := &libcontainerd.LayerOption{}
|
||||
|
||||
@@ -6,6 +6,7 @@ package daemon
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
@@ -42,8 +43,19 @@ func (daemon *Daemon) setupMounts(c *container.Container) ([]container.Mount, er
|
||||
if err := daemon.lazyInitializeVolume(c.ID, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If the daemon is being shutdown, we should not let a container start if it is trying to
|
||||
// mount the socket the daemon is listening on. During daemon shutdown, the socket
|
||||
// (/var/run/docker.sock by default) doesn't exist anymore causing the call to m.Setup to
|
||||
// create at directory instead. This in turn will prevent the daemon to restart.
|
||||
checkfunc := func(m *volume.MountPoint) error {
|
||||
if _, exist := daemon.hosts[m.Source]; exist && daemon.IsShuttingDown() {
|
||||
return fmt.Errorf("Could not mount %q to container while the daemon is shutting down", m.Source)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
||||
path, err := m.Setup(c.MountLabel, rootUID, rootGID)
|
||||
path, err := m.Setup(c.MountLabel, rootUID, rootGID, checkfunc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ func (daemon *Daemon) setupMounts(c *container.Container) ([]container.Mount, er
|
||||
if err := daemon.lazyInitializeVolume(c.ID, mount); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s, err := mount.Setup(c.MountLabel, 0, 0)
|
||||
s, err := mount.Setup(c.MountLabel, 0, 0, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ on all subcommands (due to it conflicting with, e.g. `-h` / `--hostname` on
|
||||
### `-e` and `--email` flags on `docker login`
|
||||
**Deprecated In Release: [v1.11.0](https://github.com/docker/docker/releases/tag/v1.11.0)**
|
||||
|
||||
**Target For Removal In Release: v17.06**
|
||||
**Removed In Release: [v17.06](https://github.com/docker/docker-ce/releases/tag/v17.06.0-ce)**
|
||||
|
||||
The docker login command is removing the ability to automatically register for an account with the target registry if the given username doesn't exist. Due to this change, the email flag is no longer required, and will be deprecated.
|
||||
|
||||
@@ -292,7 +292,7 @@ of the `--changes` flag that allows to pass `Dockerfile` commands.
|
||||
|
||||
**Target For Removal In Release: v17.12**
|
||||
|
||||
Version 1.9 adds a flag (`--disable-legacy-registry=false`) which prevents the
|
||||
Version 1.8.3 added a flag (`--disable-legacy-registry=false`) which prevents the
|
||||
docker daemon from `pull`, `push`, and `login` operations against v1
|
||||
registries. Though enabled by default, this signals the intent to deprecate
|
||||
the v1 protocol.
|
||||
|
||||
@@ -42,7 +42,7 @@ Options:
|
||||
--default-gateway-v6 ip Container default gateway IPv6 address
|
||||
--default-runtime string Default OCI runtime for containers (default "runc")
|
||||
--default-ulimit ulimit Default ulimits for containers (default [])
|
||||
--disable-legacy-registry Disable contacting legacy registries
|
||||
--disable-legacy-registry Disable contacting legacy registries (default true)
|
||||
--dns list DNS server to use (default [])
|
||||
--dns-opt list DNS options to use (default [])
|
||||
--dns-search list DNS search domains to use (default [])
|
||||
@@ -901,7 +901,18 @@ system's list of trusted CAs instead of enabling `--insecure-registry`.
|
||||
|
||||
##### Legacy Registries
|
||||
|
||||
Enabling `--disable-legacy-registry` forces a docker daemon to only interact with registries which support the V2 protocol. Specifically, the daemon will not attempt `push`, `pull` and `login` to v1 registries. The exception to this is `search` which can still be performed on v1 registries.
|
||||
Operations against registries supporting only the legacy v1 protocol are
|
||||
disabled by default. Specifically, the daemon will not attempt `push`,
|
||||
`pull` and `login` to v1 registries. The exception to this is `search`
|
||||
which can still be performed on v1 registries.
|
||||
|
||||
Add `"disable-legacy-registry":false` to the [daemon configuration
|
||||
file](#daemon-configuration-file), or set the
|
||||
`--disable-legacy-registry=false` flag, if you need to interact with
|
||||
registries that have not yet migrated to the v2 protocol.
|
||||
|
||||
Interaction v1 registries will no longer be supported in Docker v17.12,
|
||||
and the `disable-legacy-registry` configuration option will be removed.
|
||||
|
||||
#### Running a Docker daemon behind an HTTPS_PROXY
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
TOMLV_COMMIT=9baf8a8a9f2ed20a8e54160840c492f937eeaf9a
|
||||
|
||||
# When updating RUNC_COMMIT, also update runc in vendor.conf accordingly
|
||||
RUNC_COMMIT=992a5be178a62e026f4069f443c6164912adbf09
|
||||
CONTAINERD_COMMIT=3addd840653146c90a254301d6c3a663c7fd6429
|
||||
RUNC_COMMIT=2d41c047c83e09a6d61d464906feb2a2f3c52aa4
|
||||
CONTAINERD_COMMIT=cfb82a876ecc11b5ca0977d1733adbe58599088a
|
||||
TINI_COMMIT=949e6facb77383876aeff8a6944dde66b3089574
|
||||
LIBNETWORK_COMMIT=7b2b1feb1de4817d522cc372af149ff48d25028e
|
||||
VNDR_COMMIT=c56e082291115e369f77601f9c071dd0b87c7120
|
||||
|
||||
@@ -20,7 +20,7 @@ RUNC_BUILDTAGS="${RUNC_BUILDTAGS:-"seccomp apparmor selinux"}"
|
||||
|
||||
install_runc() {
|
||||
echo "Install runc version $RUNC_COMMIT"
|
||||
git clone https://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc"
|
||||
git clone https://github.com/docker/runc.git "$GOPATH/src/github.com/opencontainers/runc"
|
||||
cd "$GOPATH/src/github.com/opencontainers/runc"
|
||||
git checkout -q "$RUNC_COMMIT"
|
||||
make BUILDTAGS="$RUNC_BUILDTAGS" $1
|
||||
|
||||
@@ -37,6 +37,7 @@ func deployStack(unusedCli *client.Client, stackName, composeFilePath string) er
|
||||
{"docker", "stack", "deploy",
|
||||
"--compose-file", composeFilePath,
|
||||
"--with-registry-auth",
|
||||
"--resolve-image", "never",
|
||||
stackName},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ if ! command -v "$TEST_CLIENT_BINARY" &> /dev/null; then
|
||||
false
|
||||
fi
|
||||
|
||||
export DOCKER_CLI_VERSION=$(${TEST_CLIENT_BINARY} --version | awk '{ gsub(",", " "); print $3 }')
|
||||
|
||||
# This is a temporary hack for split-binary mode. It can be removed once
|
||||
# https://github.com/docker/docker/pull/22134 is merged into docker master
|
||||
if [ "$(go env GOOS)" = 'windows' ]; then
|
||||
|
||||
@@ -60,6 +60,7 @@ test_env() {
|
||||
# use "env -i" to tightly control the environment variables that bleed into the tests
|
||||
env -i \
|
||||
DEST="$DEST" \
|
||||
DOCKER_CLI_VERSION="$DOCKER_CLI_VERSION" \
|
||||
DOCKER_API_VERSION="$DOCKER_API_VERSION" \
|
||||
DOCKER_INTEGRATION_DAEMON_DEST="$DOCKER_INTEGRATION_DAEMON_DEST" \
|
||||
DOCKER_TLS_VERIFY="$DOCKER_TEST_TLS_VERIFY" \
|
||||
|
||||
@@ -2,9 +2,12 @@ package fakecontext
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
)
|
||||
|
||||
type testingT interface {
|
||||
@@ -110,3 +113,12 @@ func (f *Fake) Delete(file string) error {
|
||||
func (f *Fake) Close() error {
|
||||
return os.RemoveAll(f.Dir)
|
||||
}
|
||||
|
||||
// AsTarReader returns a ReadCloser with the contents of Dir as a tar archive.
|
||||
func (f *Fake) AsTarReader(t testingT) io.ReadCloser {
|
||||
reader, err := archive.TarWithOptions(f.Dir, &archive.TarOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create tar from %s: %s", f.Dir, err)
|
||||
}
|
||||
return reader
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ func (s *DockerSuite) TestGetContainersAttachWebsocket(c *check.C) {
|
||||
|
||||
// regression gh14320
|
||||
func (s *DockerSuite) TestPostContainersAttachContainerNotFound(c *check.C) {
|
||||
client, err := request.NewClient(daemonHost())
|
||||
client, err := request.NewHTTPClient(daemonHost())
|
||||
c.Assert(err, checker.IsNil)
|
||||
req, err := request.New(daemonHost(), "/containers/doesnotexist/attach", request.Method(http.MethodPost))
|
||||
resp, err := client.Do(req)
|
||||
|
||||
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"regexp"
|
||||
@@ -15,6 +16,9 @@ import (
|
||||
"github.com/docker/docker/integration-cli/request"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func (s *DockerSuite) TestBuildAPIDockerFileRemote(c *check.C) {
|
||||
@@ -249,3 +253,93 @@ func (s *DockerSuite) TestBuildAPIUnnormalizedTarPaths(c *check.C) {
|
||||
|
||||
c.Assert(imageA, checker.Not(checker.Equals), imageB)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildOnBuildWithCopy(c *check.C) {
|
||||
dockerfile := `
|
||||
FROM ` + minimalBaseImage() + ` as onbuildbase
|
||||
ONBUILD COPY file /file
|
||||
|
||||
FROM onbuildbase
|
||||
`
|
||||
ctx := fakecontext.New(c, "",
|
||||
fakecontext.WithDockerfile(dockerfile),
|
||||
fakecontext.WithFile("file", "some content"),
|
||||
)
|
||||
defer ctx.Close()
|
||||
|
||||
res, body, err := request.Post(
|
||||
"/build",
|
||||
request.RawContent(ctx.AsTarReader(c)),
|
||||
request.ContentType("application/x-tar"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
|
||||
|
||||
out, err := testutil.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(out), checker.Contains, "Successfully built")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildOnBuildCache(c *check.C) {
|
||||
build := func(dockerfile string) []byte {
|
||||
ctx := fakecontext.New(c, "",
|
||||
fakecontext.WithDockerfile(dockerfile),
|
||||
)
|
||||
defer ctx.Close()
|
||||
|
||||
res, body, err := request.Post(
|
||||
"/build",
|
||||
request.RawContent(ctx.AsTarReader(c)),
|
||||
request.ContentType("application/x-tar"))
|
||||
require.NoError(c, err)
|
||||
assert.Equal(c, http.StatusOK, res.StatusCode)
|
||||
|
||||
out, err := testutil.ReadBody(body)
|
||||
require.NoError(c, err)
|
||||
assert.Contains(c, string(out), "Successfully built")
|
||||
return out
|
||||
}
|
||||
|
||||
dockerfile := `
|
||||
FROM ` + minimalBaseImage() + ` as onbuildbase
|
||||
ENV something=bar
|
||||
ONBUILD ENV foo=bar
|
||||
`
|
||||
build(dockerfile)
|
||||
|
||||
dockerfile += "FROM onbuildbase"
|
||||
out := build(dockerfile)
|
||||
|
||||
imageIDs := getImageIDsFromBuild(c, out)
|
||||
assert.Len(c, imageIDs, 2)
|
||||
parentID, childID := imageIDs[0], imageIDs[1]
|
||||
|
||||
client, err := request.NewClient()
|
||||
require.NoError(c, err)
|
||||
|
||||
// check parentID is correct
|
||||
image, _, err := client.ImageInspectWithRaw(context.Background(), childID)
|
||||
require.NoError(c, err)
|
||||
assert.Equal(c, parentID, image.Parent)
|
||||
}
|
||||
|
||||
type buildLine struct {
|
||||
Stream string
|
||||
Aux struct {
|
||||
ID string
|
||||
}
|
||||
}
|
||||
|
||||
func getImageIDsFromBuild(c *check.C, output []byte) []string {
|
||||
ids := []string{}
|
||||
for _, line := range bytes.Split(output, []byte("\n")) {
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
entry := buildLine{}
|
||||
require.NoError(c, json.Unmarshal(line, &entry))
|
||||
if entry.Aux.ID != "" {
|
||||
ids = append(ids, entry.Aux.ID)
|
||||
}
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
@@ -1933,3 +1933,18 @@ func (s *DockerSuite) TestContainersAPICreateMountsTmpfs(c *check.C) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Regression test for #33334
|
||||
// Makes sure that when a container which has a custom stop signal + restart=always
|
||||
// gets killed (with SIGKILL) by the kill API, that the restart policy is cancelled.
|
||||
func (s *DockerSuite) TestContainerKillCustomStopSignal(c *check.C) {
|
||||
id := strings.TrimSpace(runSleepingContainer(c, "--stop-signal=SIGTERM", "--restart=always"))
|
||||
res, _, err := request.Post("/containers/" + id + "/kill")
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer res.Body.Close()
|
||||
|
||||
b, err := ioutil.ReadAll(res.Body)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusNoContent, check.Commentf(string(b)))
|
||||
err = waitInspect(id, "{{.State.Running}} {{.State.Restarting}}", "false false", 30*time.Second)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
@@ -966,20 +966,21 @@ func (s *DockerSwarmSuite) TestSwarmRepeatedRootRotation(c *check.C) {
|
||||
for j := 0; j < 18; j++ {
|
||||
info, err := m.SwarmInfo()
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(info.Cluster.Spec.CAConfig.SigningCACert, checker.Equals, expectedCert)
|
||||
// the desired CA key is always redacted
|
||||
|
||||
// the desired CA cert and key is always redacted
|
||||
c.Assert(info.Cluster.Spec.CAConfig.SigningCAKey, checker.Equals, "")
|
||||
c.Assert(info.Cluster.Spec.CAConfig.SigningCACert, checker.Equals, "")
|
||||
|
||||
clusterTLSInfo = info.Cluster.TLSInfo
|
||||
|
||||
if !info.Cluster.RootRotationInProgress {
|
||||
// if root rotation is done and the trust root has changed, we don't have to poll anymore
|
||||
if !info.Cluster.RootRotationInProgress && clusterTLSInfo.TrustRoot != currentTrustRoot {
|
||||
break
|
||||
}
|
||||
|
||||
// root rotation not done
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
}
|
||||
c.Assert(clusterTLSInfo.TrustRoot, checker.Not(checker.Equals), currentTrustRoot)
|
||||
if cert != nil {
|
||||
c.Assert(clusterTLSInfo.TrustRoot, checker.Equals, expectedCert)
|
||||
}
|
||||
|
||||
@@ -58,8 +58,7 @@ func (s *DockerSuite) TestConfigHTTPHeader(c *check.C) {
|
||||
|
||||
c.Assert(headers["User-Agent"], checker.NotNil, check.Commentf("Missing User-Agent"))
|
||||
|
||||
//TODO(tiborvass): restore dockerversion.Version instead of library-import
|
||||
c.Assert(headers["User-Agent"][0], checker.Equals, "Docker-Client/unknown-version ("+runtime.GOOS+")", check.Commentf("Badly formatted User-Agent,out:%v", result.Combined()))
|
||||
c.Assert(headers["User-Agent"][0], checker.Equals, "Docker-Client/"+os.Getenv("DOCKER_CLI_VERSION")+" ("+runtime.GOOS+")", check.Commentf("Badly formatted User-Agent,out:%v", result.Combined()))
|
||||
|
||||
c.Assert(headers["Myheader"], checker.NotNil)
|
||||
c.Assert(headers["Myheader"][0], checker.Equals, "MyValue", check.Commentf("Missing/bad header,out:%v", result.Combined()))
|
||||
|
||||
@@ -139,3 +139,26 @@ func (s *DockerSuite) TestHealth(c *check.C) {
|
||||
c.Check(out, checker.Equals, "[CMD cat /my status]\n")
|
||||
|
||||
}
|
||||
|
||||
// Github #33021
|
||||
func (s *DockerSuite) TestUnsetEnvVarHealthCheck(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux) // busybox doesn't work on Windows
|
||||
|
||||
imageName := "testhealth"
|
||||
buildImageSuccessfully(c, imageName, build.WithDockerfile(`FROM busybox
|
||||
HEALTHCHECK --interval=1s --timeout=5s --retries=5 CMD /bin/sh -c "sleep 1"
|
||||
ENTRYPOINT /bin/sh -c "sleep 600"`))
|
||||
|
||||
name := "env_test_health"
|
||||
// No health status before starting
|
||||
dockerCmd(c, "run", "-d", "--name", name, "-e", "FOO", imageName)
|
||||
defer func() {
|
||||
dockerCmd(c, "rm", "-f", name)
|
||||
dockerCmd(c, "rmi", imageName)
|
||||
}()
|
||||
|
||||
// Start
|
||||
dockerCmd(c, "start", name)
|
||||
waitForHealthStatus(c, name, "starting", "healthy")
|
||||
|
||||
}
|
||||
|
||||
@@ -28,17 +28,3 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestLoginToPrivateRegistry(c *check.C)
|
||||
// now it's fine
|
||||
dockerCmd(c, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL)
|
||||
}
|
||||
|
||||
func (s *DockerRegistryAuthHtpasswdSuite) TestLoginToPrivateRegistryDeprecatedEmailFlag(c *check.C) {
|
||||
// Test to make sure login still works with the deprecated -e and --email flags
|
||||
// wrong credentials
|
||||
out, _, err := dockerCmdWithError("login", "-u", s.reg.Username(), "-p", "WRONGPASSWORD", "-e", s.reg.Email(), privateRegistryURL)
|
||||
c.Assert(err, checker.NotNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "401 Unauthorized")
|
||||
|
||||
// now it's fine
|
||||
// -e flag
|
||||
dockerCmd(c, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), "-e", s.reg.Email(), privateRegistryURL)
|
||||
// --email flag
|
||||
dockerCmd(c, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), "--email", s.reg.Email(), privateRegistryURL)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ import (
|
||||
)
|
||||
|
||||
func (s *DockerRegistryAuthHtpasswdSuite) TestLogoutWithExternalAuth(c *check.C) {
|
||||
|
||||
// @TODO TestLogoutWithExternalAuth expects docker to fall back to a v1 registry, so has to be updated for v17.12, when v1 registries are no longer supported
|
||||
s.d.StartWithBusybox(c, "--disable-legacy-registry=false")
|
||||
|
||||
osPath := os.Getenv("PATH")
|
||||
defer os.Setenv("PATH", osPath)
|
||||
|
||||
@@ -28,6 +32,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestLogoutWithExternalAuth(c *check.C)
|
||||
|
||||
tmp, err := ioutil.TempDir("", "integration-cli-")
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
externalAuthConfig := `{ "credsStore": "shell-test" }`
|
||||
|
||||
@@ -35,24 +40,27 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestLogoutWithExternalAuth(c *check.C)
|
||||
err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
dockerCmd(c, "--config", tmp, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL)
|
||||
_, err = s.d.Cmd("--config", tmp, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
b, err := ioutil.ReadFile(configPath)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(b), checker.Not(checker.Contains), "\"auth\":")
|
||||
c.Assert(string(b), checker.Contains, privateRegistryURL)
|
||||
|
||||
dockerCmd(c, "--config", tmp, "tag", "busybox", repoName)
|
||||
dockerCmd(c, "--config", tmp, "push", repoName)
|
||||
|
||||
dockerCmd(c, "--config", tmp, "logout", privateRegistryURL)
|
||||
_, err = s.d.Cmd("--config", tmp, "tag", "busybox", repoName)
|
||||
c.Assert(err, checker.IsNil)
|
||||
_, err = s.d.Cmd("--config", tmp, "push", repoName)
|
||||
c.Assert(err, checker.IsNil)
|
||||
_, err = s.d.Cmd("--config", tmp, "logout", privateRegistryURL)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
b, err = ioutil.ReadFile(configPath)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(b), checker.Not(checker.Contains), privateRegistryURL)
|
||||
|
||||
// check I cannot pull anymore
|
||||
out, _, err := dockerCmdWithError("--config", tmp, "pull", repoName)
|
||||
out, err := s.d.Cmd("--config", tmp, "pull", repoName)
|
||||
c.Assert(err, check.NotNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "Error: image dockercli/busybox:authtest not found")
|
||||
}
|
||||
|
||||
@@ -258,10 +258,13 @@ func (s *DockerHubPullSuite) TestPullClientDisconnect(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerRegistryAuthHtpasswdSuite) TestPullNoCredentialsNotFound(c *check.C) {
|
||||
// @TODO TestPullNoCredentialsNotFound expects docker to fall back to a v1 registry, so has to be updated for v17.12, when v1 registries are no longer supported
|
||||
s.d.StartWithBusybox(c, "--disable-legacy-registry=false")
|
||||
|
||||
// we don't care about the actual image, we just want to see image not found
|
||||
// because that means v2 call returned 401 and we fell back to v1 which usually
|
||||
// gives a 404 (in this case the test registry doesn't handle v1 at all)
|
||||
out, _, err := dockerCmdWithError("pull", privateRegistryURL+"/busybox")
|
||||
out, err := s.d.Cmd("pull", privateRegistryURL+"/busybox")
|
||||
c.Assert(err, check.NotNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "Error: image busybox:latest not found")
|
||||
}
|
||||
|
||||
@@ -98,8 +98,7 @@ func (s *DockerRegistrySuite) TestUserAgentPassThrough(c *check.C) {
|
||||
"--insecure-registry", buildReg.URL(),
|
||||
"--insecure-registry", pullReg.URL(),
|
||||
"--insecure-registry", pushReg.URL(),
|
||||
"--insecure-registry", loginReg.URL(),
|
||||
"--disable-legacy-registry=true")
|
||||
"--insecure-registry", loginReg.URL())
|
||||
|
||||
dockerfileName, cleanup1, err := makefile(fmt.Sprintf("FROM %s", buildRepoName))
|
||||
c.Assert(err, check.IsNil, check.Commentf("Unable to create test dockerfile"))
|
||||
@@ -107,7 +106,7 @@ func (s *DockerRegistrySuite) TestUserAgentPassThrough(c *check.C) {
|
||||
s.d.Cmd("build", "--file", dockerfileName, ".")
|
||||
regexpCheckUA(c, buildUA)
|
||||
|
||||
s.d.Cmd("login", "-u", "richard", "-p", "testtest", "-e", "testuser@testdomain.com", loginReg.URL())
|
||||
s.d.Cmd("login", "-u", "richard", "-p", "testtest", loginReg.URL())
|
||||
regexpCheckUA(c, loginUA)
|
||||
|
||||
s.d.Cmd("pull", pullRepoName)
|
||||
|
||||
@@ -410,3 +410,38 @@ func (s *DockerSwarmSuite) TestServiceCreateMountTmpfs(c *check.C) {
|
||||
c.Assert(strings.TrimSpace(out), checker.HasPrefix, "tmpfs on /foo type tmpfs")
|
||||
c.Assert(strings.TrimSpace(out), checker.Contains, "size=1024k")
|
||||
}
|
||||
|
||||
func (s *DockerSwarmSuite) TestServiceCreateWithNetworkAlias(c *check.C) {
|
||||
d := s.AddDaemon(c, true, true)
|
||||
out, err := d.Cmd("network", "create", "--scope=swarm", "test_swarm_br")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
||||
out, err = d.Cmd("service", "create", "--no-resolve-image", "--detach=true", "--network=name=test_swarm_br,alias=srv_alias", "--name=alias_tst_container", "busybox", "top")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
id := strings.TrimSpace(out)
|
||||
|
||||
var tasks []swarm.Task
|
||||
waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
|
||||
tasks = d.GetServiceTasks(c, id)
|
||||
return len(tasks) > 0, nil
|
||||
}, checker.Equals, true)
|
||||
|
||||
task := tasks[0]
|
||||
waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
|
||||
if task.NodeID == "" || task.Status.ContainerStatus.ContainerID == "" {
|
||||
task = d.GetTask(c, task.ID)
|
||||
}
|
||||
return task.NodeID != "" && task.Status.ContainerStatus.ContainerID != "", nil
|
||||
}, checker.Equals, true)
|
||||
|
||||
// check container alias config
|
||||
out, err = s.nodeCmd(c, task.NodeID, "inspect", "--format", "{{json .NetworkSettings.Networks.test_swarm_br.Aliases}}", task.Status.ContainerStatus.ContainerID)
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
||||
// Make sure the only alias seen is the container-id
|
||||
var aliases []string
|
||||
c.Assert(json.Unmarshal([]byte(out), &aliases), checker.IsNil)
|
||||
c.Assert(aliases, checker.HasLen, 1)
|
||||
|
||||
c.Assert(task.Status.ContainerStatus.ContainerID, checker.Contains, aliases[0])
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ func (s *DockerSwarmSuite) TestServiceLogs(c *check.C) {
|
||||
// make sure task has been deployed.
|
||||
waitAndAssert(c, defaultReconciliationTimeout,
|
||||
d.CheckRunningTaskImages, checker.DeepEquals,
|
||||
map[string]int{"busybox": len(services)})
|
||||
map[string]int{"busybox:latest": len(services)})
|
||||
|
||||
for name, message := range services {
|
||||
out, err := d.Cmd("service", "logs", name)
|
||||
@@ -287,7 +287,7 @@ func (s *DockerSwarmSuite) TestServiceLogsTTY(c *check.C) {
|
||||
result = icmd.RunCmd(cmd)
|
||||
// for some reason there is carriage return in the output. i think this is
|
||||
// just expected.
|
||||
c.Assert(result, icmd.Matches, icmd.Expected{Out: "out\nerr\n"})
|
||||
c.Assert(result, icmd.Matches, icmd.Expected{Out: "out\r\nerr\r\n"})
|
||||
}
|
||||
|
||||
func (s *DockerSwarmSuite) TestServiceLogsNoHangDeletedContainer(c *check.C) {
|
||||
|
||||
@@ -62,6 +62,7 @@ func (s *DockerSwarmSuite) TestStackDeployComposeFile(c *check.C) {
|
||||
testStackName := "testdeploy"
|
||||
stackArgs := []string{
|
||||
"stack", "deploy",
|
||||
"--resolve-image", "never",
|
||||
"--compose-file", "fixtures/deploy/default.yaml",
|
||||
testStackName,
|
||||
}
|
||||
@@ -88,6 +89,7 @@ func (s *DockerSwarmSuite) TestStackDeployWithSecretsTwice(c *check.C) {
|
||||
testStackName := "testdeploy"
|
||||
stackArgs := []string{
|
||||
"stack", "deploy",
|
||||
"--resolve-image", "never",
|
||||
"--compose-file", "fixtures/deploy/secrets.yaml",
|
||||
testStackName,
|
||||
}
|
||||
@@ -120,6 +122,7 @@ func (s *DockerSwarmSuite) TestStackRemove(c *check.C) {
|
||||
stackName := "testdeploy"
|
||||
stackArgs := []string{
|
||||
"stack", "deploy",
|
||||
"--resolve-image", "never",
|
||||
"--compose-file", "fixtures/deploy/remove.yaml",
|
||||
stackName,
|
||||
}
|
||||
@@ -179,6 +182,7 @@ func (s *DockerSwarmSuite) TestStackDeployWithDAB(c *check.C) {
|
||||
// deploy
|
||||
stackArgs := []string{
|
||||
"stack", "deploy",
|
||||
"--resolve-image", "never",
|
||||
"--bundle-file", testDABFileName,
|
||||
testStackName,
|
||||
}
|
||||
|
||||
@@ -2002,6 +2002,35 @@ func (s *DockerSwarmSuite) TestSwarmJoinLeave(c *check.C) {
|
||||
}
|
||||
}
|
||||
|
||||
const defaultRetryCount = 10
|
||||
|
||||
func waitForEvent(c *check.C, d *daemon.Swarm, since string, filter string, event string, retry int) string {
|
||||
if retry < 1 {
|
||||
c.Fatalf("retry count %d is invalid. It should be no less than 1", retry)
|
||||
return ""
|
||||
}
|
||||
var out string
|
||||
for i := 0; i < retry; i++ {
|
||||
until := daemonUnixTime(c)
|
||||
var err error
|
||||
if len(filter) > 0 {
|
||||
out, err = d.Cmd("events", "--since", since, "--until", until, filter)
|
||||
} else {
|
||||
out, err = d.Cmd("events", "--since", since, "--until", until)
|
||||
}
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
if strings.Contains(out, event) {
|
||||
return strings.TrimSpace(out)
|
||||
}
|
||||
// no need to sleep after last retry
|
||||
if i < retry-1 {
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
c.Fatalf("docker events output '%s' doesn't contain event '%s'", out, event)
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s *DockerSwarmSuite) TestSwarmClusterEventsSource(c *check.C) {
|
||||
d1 := s.AddDaemon(c, true, true)
|
||||
d2 := s.AddDaemon(c, true, true)
|
||||
@@ -2013,21 +2042,13 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsSource(c *check.C) {
|
||||
networkID := strings.TrimSpace(out)
|
||||
c.Assert(networkID, checker.Not(checker.Equals), "")
|
||||
|
||||
until := daemonUnixTime(c)
|
||||
// d1 is a manager
|
||||
out, err = d1.Cmd("events", "--since=0", "--until", until, "-f scope=swarm")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(strings.TrimSpace(out), checker.Contains, "network create "+networkID)
|
||||
|
||||
// d2 is a manager
|
||||
out, err = d2.Cmd("events", "--since=0", "--until", until, "-f scope=swarm")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(strings.TrimSpace(out), checker.Contains, "network create "+networkID)
|
||||
// d1, d2 are managers that can get swarm events
|
||||
waitForEvent(c, d1, "0", "-f scope=swarm", "network create "+networkID, defaultRetryCount)
|
||||
waitForEvent(c, d2, "0", "-f scope=swarm", "network create "+networkID, defaultRetryCount)
|
||||
|
||||
// d3 is a worker, not able to get cluster events
|
||||
out, err = d3.Cmd("events", "--since=0", "--until", until, "-f scope=swarm")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), "network create ")
|
||||
out = waitForEvent(c, d3, "0", "-f scope=swarm", "", 1)
|
||||
c.Assert(out, checker.Not(checker.Contains), "network create ")
|
||||
}
|
||||
|
||||
func (s *DockerSwarmSuite) TestSwarmClusterEventsScope(c *check.C) {
|
||||
@@ -2038,24 +2059,17 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsScope(c *check.C) {
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
serviceID := strings.Split(out, "\n")[0]
|
||||
|
||||
until := daemonUnixTime(c)
|
||||
// scope swarm filters cluster events
|
||||
out, err = d.Cmd("events", "--since=0", "--until", until, "-f scope=swarm")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(strings.TrimSpace(out), checker.Contains, "service create "+serviceID)
|
||||
c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), "container create ")
|
||||
out = waitForEvent(c, d, "0", "-f scope=swarm", "service create "+serviceID, defaultRetryCount)
|
||||
c.Assert(out, checker.Not(checker.Contains), "container create ")
|
||||
|
||||
// without scope all events are returned
|
||||
out, err = d.Cmd("events", "--since=0", "--until", until)
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(strings.TrimSpace(out), checker.Contains, "service create "+serviceID)
|
||||
c.Assert(strings.TrimSpace(out), checker.Contains, "container create ")
|
||||
// all events are returned if scope is not specified
|
||||
waitForEvent(c, d, "0", "", "service create "+serviceID, 1)
|
||||
waitForEvent(c, d, "0", "", "container create ", defaultRetryCount)
|
||||
|
||||
// scope local only show non-cluster events
|
||||
out, err = d.Cmd("events", "--since=0", "--until", until, "-f scope=local")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), "service create ")
|
||||
c.Assert(strings.TrimSpace(out), checker.Contains, "container create ")
|
||||
// scope local only shows non-cluster events
|
||||
out = waitForEvent(c, d, "0", "-f scope=local", "container create ", 1)
|
||||
c.Assert(out, checker.Not(checker.Contains), "service create ")
|
||||
}
|
||||
|
||||
func (s *DockerSwarmSuite) TestSwarmClusterEventsType(c *check.C) {
|
||||
@@ -2072,17 +2086,12 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsType(c *check.C) {
|
||||
networkID := strings.TrimSpace(out)
|
||||
c.Assert(networkID, checker.Not(checker.Equals), "")
|
||||
|
||||
until := daemonUnixTime(c)
|
||||
// filter by service
|
||||
out, err = d.Cmd("events", "--since=0", "--until", until, "-f type=service")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "service create "+serviceID)
|
||||
out = waitForEvent(c, d, "0", "-f type=service", "service create "+serviceID, defaultRetryCount)
|
||||
c.Assert(out, checker.Not(checker.Contains), "network create")
|
||||
|
||||
// filter by network
|
||||
out, err = d.Cmd("events", "--since=0", "--until", until, "-f type=network")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "network create "+networkID)
|
||||
out = waitForEvent(c, d, "0", "-f type=network", "network create "+networkID, defaultRetryCount)
|
||||
c.Assert(out, checker.Not(checker.Contains), "service create")
|
||||
}
|
||||
|
||||
@@ -2094,40 +2103,36 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsService(c *check.C) {
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
serviceID := strings.Split(out, "\n")[0]
|
||||
|
||||
t1 := daemonUnixTime(c)
|
||||
// validate service create event
|
||||
out, err = d.Cmd("events", "--since=0", "--until", t1, "-f scope=swarm")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "service create "+serviceID)
|
||||
waitForEvent(c, d, "0", "-f scope=swarm", "service create "+serviceID, defaultRetryCount)
|
||||
|
||||
t1 := daemonUnixTime(c)
|
||||
out, err = d.Cmd("service", "update", "--force", "--detach=false", "test")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
||||
t2 := daemonUnixTime(c)
|
||||
out, err = d.Cmd("events", "--since", t1, "--until", t2, "-f scope=swarm")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "service update "+serviceID)
|
||||
// wait for service update start
|
||||
out = waitForEvent(c, d, t1, "-f scope=swarm", "service update "+serviceID, defaultRetryCount)
|
||||
c.Assert(out, checker.Contains, "updatestate.new=updating")
|
||||
|
||||
// allow service update complete. This is a service with 1 instance
|
||||
time.Sleep(400 * time.Millisecond)
|
||||
out = waitForEvent(c, d, t1, "-f scope=swarm", "service update "+serviceID, defaultRetryCount)
|
||||
c.Assert(out, checker.Contains, "updatestate.new=completed, updatestate.old=updating")
|
||||
|
||||
// scale service
|
||||
t2 := daemonUnixTime(c)
|
||||
out, err = d.Cmd("service", "scale", "test=3")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
||||
t3 := daemonUnixTime(c)
|
||||
out, err = d.Cmd("events", "--since", t2, "--until", t3, "-f scope=swarm")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "service update "+serviceID)
|
||||
out = waitForEvent(c, d, t2, "-f scope=swarm", "service update "+serviceID, defaultRetryCount)
|
||||
c.Assert(out, checker.Contains, "replicas.new=3, replicas.old=1")
|
||||
|
||||
// remove service
|
||||
t3 := daemonUnixTime(c)
|
||||
out, err = d.Cmd("service", "rm", "test")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
||||
t4 := daemonUnixTime(c)
|
||||
out, err = d.Cmd("events", "--since", t3, "--until", t4, "-f scope=swarm")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "service remove "+serviceID)
|
||||
waitForEvent(c, d, t3, "-f scope=swarm", "service remove "+serviceID, defaultRetryCount)
|
||||
}
|
||||
|
||||
func (s *DockerSwarmSuite) TestSwarmClusterEventsNode(c *check.C) {
|
||||
@@ -2136,38 +2141,28 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsNode(c *check.C) {
|
||||
d3 := s.AddDaemon(c, true, true)
|
||||
|
||||
d3ID := d3.NodeID
|
||||
waitForEvent(c, d1, "0", "-f scope=swarm", "node create "+d3ID, defaultRetryCount)
|
||||
|
||||
t1 := daemonUnixTime(c)
|
||||
out, err := d1.Cmd("events", "--since=0", "--until", t1, "-f scope=swarm")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "node create "+d3ID)
|
||||
|
||||
out, err = d1.Cmd("node", "update", "--availability=pause", d3ID)
|
||||
out, err := d1.Cmd("node", "update", "--availability=pause", d3ID)
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
||||
t2 := daemonUnixTime(c)
|
||||
// filter by type
|
||||
out, err = d1.Cmd("events", "--since", t1, "--until", t2, "-f type=node")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "node update "+d3ID)
|
||||
out = waitForEvent(c, d1, t1, "-f type=node", "node update "+d3ID, defaultRetryCount)
|
||||
c.Assert(out, checker.Contains, "availability.new=pause, availability.old=active")
|
||||
|
||||
t2 := daemonUnixTime(c)
|
||||
out, err = d1.Cmd("node", "demote", d3ID)
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
||||
t3 := daemonUnixTime(c)
|
||||
// filter by type and scope
|
||||
out, err = d1.Cmd("events", "--since", t2, "--until", t3, "-f type=node", "-f scope=swarm")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "node update "+d3ID)
|
||||
waitForEvent(c, d1, t2, "-f type=node", "node update "+d3ID, defaultRetryCount)
|
||||
|
||||
t3 := daemonUnixTime(c)
|
||||
out, err = d1.Cmd("node", "rm", "-f", d3ID)
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
||||
t4 := daemonUnixTime(c)
|
||||
// filter by type and scope
|
||||
out, err = d1.Cmd("events", "--since", t3, "--until", t4, "-f type=node", "-f scope=swarm")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "node remove "+d3ID)
|
||||
// filter by scope
|
||||
waitForEvent(c, d1, t3, "-f scope=swarm", "node remove "+d3ID, defaultRetryCount)
|
||||
}
|
||||
|
||||
func (s *DockerSwarmSuite) TestSwarmClusterEventsNetwork(c *check.C) {
|
||||
@@ -2178,20 +2173,15 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsNetwork(c *check.C) {
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
networkID := strings.TrimSpace(out)
|
||||
|
||||
t1 := daemonUnixTime(c)
|
||||
out, err = d.Cmd("events", "--since=0", "--until", t1, "-f scope=swarm")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "network create "+networkID)
|
||||
waitForEvent(c, d, "0", "-f scope=swarm", "network create "+networkID, defaultRetryCount)
|
||||
|
||||
// remove network
|
||||
t1 := daemonUnixTime(c)
|
||||
out, err = d.Cmd("network", "rm", "foo")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
||||
t2 := daemonUnixTime(c)
|
||||
// filtered by network
|
||||
out, err = d.Cmd("events", "--since", t1, "--until", t2, "-f type=network")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "network remove "+networkID)
|
||||
waitForEvent(c, d, t1, "-f type=network", "network remove "+networkID, defaultRetryCount)
|
||||
}
|
||||
|
||||
func (s *DockerSwarmSuite) TestSwarmClusterEventsSecret(c *check.C) {
|
||||
@@ -2206,15 +2196,10 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsSecret(c *check.C) {
|
||||
})
|
||||
c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id))
|
||||
|
||||
t1 := daemonUnixTime(c)
|
||||
out, err := d.Cmd("events", "--since=0", "--until", t1, "-f scope=swarm")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "secret create "+id)
|
||||
waitForEvent(c, d, "0", "-f scope=swarm", "secret create "+id, defaultRetryCount)
|
||||
|
||||
t1 := daemonUnixTime(c)
|
||||
d.DeleteSecret(c, id)
|
||||
t2 := daemonUnixTime(c)
|
||||
// filtered by secret
|
||||
out, err = d.Cmd("events", "--since", t1, "--until", t2, "-f type=secret")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "secret remove "+id)
|
||||
waitForEvent(c, d, t1, "-f type=secret", "secret remove "+id, defaultRetryCount)
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ func (s *DockerSwarmSuite) TestSwarmNetworkPluginV2(c *check.C) {
|
||||
|
||||
time.Sleep(20 * time.Second)
|
||||
|
||||
image := "busybox"
|
||||
image := "busybox:latest"
|
||||
// create a new global service again.
|
||||
_, err = d1.Cmd("service", "create", "--no-resolve-image", "--name", serviceName, "--mode=global", "--network", networkName, image, "top")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
@@ -34,7 +34,7 @@ func makefile(contents string) (string, func(), error) {
|
||||
|
||||
}
|
||||
|
||||
// TestV2Only ensures that a daemon in v2-only mode does not
|
||||
// TestV2Only ensures that a daemon by default does not
|
||||
// attempt to contact any v1 registry endpoints.
|
||||
func (s *DockerRegistrySuite) TestV2Only(c *check.C) {
|
||||
reg, err := registry.NewMock(c)
|
||||
@@ -51,7 +51,7 @@ func (s *DockerRegistrySuite) TestV2Only(c *check.C) {
|
||||
|
||||
repoName := fmt.Sprintf("%s/busybox", reg.URL())
|
||||
|
||||
s.d.Start(c, "--insecure-registry", reg.URL(), "--disable-legacy-registry=true")
|
||||
s.d.Start(c, "--insecure-registry", reg.URL())
|
||||
|
||||
dockerfileName, cleanup, err := makefile(fmt.Sprintf("FROM %s/busybox", reg.URL()))
|
||||
c.Assert(err, check.IsNil, check.Commentf("Unable to create test dockerfile"))
|
||||
@@ -60,13 +60,13 @@ func (s *DockerRegistrySuite) TestV2Only(c *check.C) {
|
||||
s.d.Cmd("build", "--file", dockerfileName, ".")
|
||||
|
||||
s.d.Cmd("run", repoName)
|
||||
s.d.Cmd("login", "-u", "richard", "-p", "testtest", "-e", "testuser@testdomain.com", reg.URL())
|
||||
s.d.Cmd("login", "-u", "richard", "-p", "testtest", reg.URL())
|
||||
s.d.Cmd("tag", "busybox", repoName)
|
||||
s.d.Cmd("push", repoName)
|
||||
s.d.Cmd("pull", repoName)
|
||||
}
|
||||
|
||||
// TestV1 starts a daemon in 'normal' mode
|
||||
// TestV1 starts a daemon with legacy registries enabled
|
||||
// and ensure v1 endpoints are hit for the following operations:
|
||||
// login, push, pull, build & run
|
||||
func (s *DockerRegistrySuite) TestV1(c *check.C) {
|
||||
|
||||
@@ -100,7 +100,7 @@ func DoOnHost(host, endpoint string, modifiers ...func(*http.Request) error) (*h
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
client, err := NewClient(host)
|
||||
client, err := NewHTTPClient(host)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -140,8 +140,8 @@ func New(host, endpoint string, modifiers ...func(*http.Request) error) (*http.R
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// NewClient creates an http client for the specific host
|
||||
func NewClient(host string) (*http.Client, error) {
|
||||
// NewHTTPClient creates an http client for the specific host
|
||||
func NewHTTPClient(host string) (*http.Client, error) {
|
||||
// FIXME(vdemeester) 10*time.Second timeout of SockRequest… ?
|
||||
proto, addr, _, err := dclient.ParseHost(host)
|
||||
if err != nil {
|
||||
@@ -163,6 +163,16 @@ func NewClient(host string) (*http.Client, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
// NewClient returns a new Docker API client
|
||||
func NewClient() (dclient.APIClient, error) {
|
||||
host := DaemonHost()
|
||||
httpClient, err := NewHTTPClient(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dclient.NewClient(host, "", httpClient, nil)
|
||||
}
|
||||
|
||||
// FIXME(vdemeester) httputil.ClientConn is deprecated, use http.Client instead (closer to actual client)
|
||||
// Deprecated: Use New instead of NewRequestClient
|
||||
// Deprecated: use request.Do (or Get, Delete, Post) instead
|
||||
|
||||
@@ -414,6 +414,18 @@ func (r *remote) runContainerdDaemon() error {
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// unless strictly necessary, do not add anything in between here
|
||||
// as the reaper goroutine below needs to kick in as soon as possible
|
||||
// and any "return" from code paths added here will defeat the reaper
|
||||
// process.
|
||||
|
||||
r.daemonWaitCh = make(chan struct{})
|
||||
go func() {
|
||||
cmd.Wait()
|
||||
close(r.daemonWaitCh)
|
||||
}() // Reap our child when needed
|
||||
|
||||
logrus.Infof("libcontainerd: new containerd process, pid: %d", cmd.Process.Pid)
|
||||
if err := setOOMScore(cmd.Process.Pid, r.oomScore); err != nil {
|
||||
system.KillProcess(cmd.Process.Pid)
|
||||
@@ -424,11 +436,6 @@ func (r *remote) runContainerdDaemon() error {
|
||||
return err
|
||||
}
|
||||
|
||||
r.daemonWaitCh = make(chan struct{})
|
||||
go func() {
|
||||
cmd.Wait()
|
||||
close(r.daemonWaitCh)
|
||||
}() // Reap our child when needed
|
||||
r.daemonPid = cmd.Process.Pid
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.7.5-alpine
|
||||
FROM golang:1.8.3-alpine
|
||||
|
||||
RUN apk add -U git bash curl gcc musl-dev make
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ FROM aarch64/ubuntu:xenial
|
||||
|
||||
RUN apt-get update && apt-get install -y git golang-go curl
|
||||
|
||||
ENV GO_VERSION 1.7.5
|
||||
ENV GO_VERSION 1.8.3
|
||||
ENV GOARCH arm64
|
||||
ENV PATH /go/bin:/usr/src/go/bin:$PATH
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user