diff --git a/Makefile b/Makefile index e31e75286..432b34cce 100644 --- a/Makefile +++ b/Makefile @@ -17,9 +17,10 @@ VERSION ?= $(shell git describe --match 'v[0-9]*' --dirty='.m' --always --tags) GO_LDFLAGS ?= -w -X ${PKG}/internal.Version=${VERSION} GO_BUILDTAGS ?= e2e - +DRIVE_PREFIX?= ifeq ($(OS),Windows_NT) DETECTED_OS = Windows + DRIVE_PREFIX=C: else DETECTED_OS = $(shell uname -s) endif @@ -122,8 +123,8 @@ docs: ## generate documentation $(eval $@_TMP_OUT := $(shell mktemp -d -t compose-output.XXXXXXXXXX)) $(BUILDX_CMD) bake --set "*.output=type=local,dest=$($@_TMP_OUT)" docs-update rm -rf ./docs/internal - cp -R "$($@_TMP_OUT)"/out/* ./docs/ - rm -rf "$($@_TMP_OUT)"/* + cp -R "$(DRIVE_PREFIX)$($@_TMP_OUT)"/out/* ./docs/ + rm -rf "$(DRIVE_PREFIX)$($@_TMP_OUT)"/* .PHONY: validate-docs validate-docs: ## validate the doc does not change diff --git a/cmd/compose/down.go b/cmd/compose/down.go index 29f7a7c0e..8a997b256 100644 --- a/cmd/compose/down.go +++ b/cmd/compose/down.go @@ -44,7 +44,7 @@ func downCommand(p *ProjectOptions, backend api.Service) *cobra.Command { ProjectOptions: p, } downCmd := &cobra.Command{ - Use: "down [OPTIONS]", + Use: "down [OPTIONS] [SERVICES]", Short: "Stop and remove containers, networks", PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error { opts.timeChanged = cmd.Flags().Changed("timeout") @@ -56,16 +56,15 @@ func downCommand(p *ProjectOptions, backend api.Service) *cobra.Command { return nil }), RunE: Adapt(func(ctx context.Context, args []string) error { - return runDown(ctx, backend, opts) + return runDown(ctx, backend, opts, args) }), - Args: cobra.NoArgs, ValidArgsFunction: noCompletion(), } flags := downCmd.Flags() removeOrphans := utils.StringToBool(os.Getenv(ComposeRemoveOrphans)) flags.BoolVar(&opts.removeOrphans, "remove-orphans", removeOrphans, "Remove containers for services not defined in the Compose file.") flags.IntVarP(&opts.timeout, "timeout", "t", 10, "Specify a shutdown timeout in seconds") - flags.BoolVarP(&opts.volumes, "volumes", "v", false, "Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers.") + flags.BoolVarP(&opts.volumes, "volumes", "v", false, `Remove named volumes declared in the "volumes" section of the Compose file and anonymous volumes attached to containers.`) flags.StringVar(&opts.images, "rmi", "", `Remove images used by services. "local" remove only images that don't have a custom tag ("local"|"all")`) flags.SetNormalizeFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName { if name == "volume" { @@ -77,7 +76,7 @@ func downCommand(p *ProjectOptions, backend api.Service) *cobra.Command { return downCmd } -func runDown(ctx context.Context, backend api.Service, opts downOptions) error { +func runDown(ctx context.Context, backend api.Service, opts downOptions, services []string) error { project, name, err := opts.projectOrName() if err != nil { return err @@ -94,5 +93,6 @@ func runDown(ctx context.Context, backend api.Service, opts downOptions) error { Timeout: timeout, Images: opts.images, Volumes: opts.volumes, + Services: services, }) } diff --git a/docs/reference/compose_down.md b/docs/reference/compose_down.md index 994ad33be..3f80f9b77 100644 --- a/docs/reference/compose_down.md +++ b/docs/reference/compose_down.md @@ -11,7 +11,7 @@ Stop and remove containers, networks | `--remove-orphans` | | | Remove containers for services not defined in the Compose file. | | `--rmi` | `string` | | Remove images used by services. "local" remove only images that don't have a custom tag ("local"\|"all") | | `-t`, `--timeout` | `int` | `10` | Specify a shutdown timeout in seconds | -| `-v`, `--volumes` | | | Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers. | +| `-v`, `--volumes` | | | Remove named volumes declared in the "volumes" section of the Compose file and anonymous volumes attached to containers. | diff --git a/docs/reference/docker_compose_down.yaml b/docs/reference/docker_compose_down.yaml index bb1ac314b..6c6724780 100644 --- a/docs/reference/docker_compose_down.yaml +++ b/docs/reference/docker_compose_down.yaml @@ -14,7 +14,7 @@ long: |- Anonymous volumes are not removed by default. However, as they don’t have a stable name, they will not be automatically mounted by a subsequent `up`. For data that needs to persist between updates, use explicit paths as bind mounts or named volumes. -usage: docker compose down [OPTIONS] +usage: docker compose down [OPTIONS] [SERVICES] pname: docker compose plink: docker_compose.yaml options: @@ -54,7 +54,7 @@ options: value_type: bool default_value: "false" description: | - Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers. + Remove named volumes declared in the "volumes" section of the Compose file and anonymous volumes attached to containers. deprecated: false hidden: false experimental: false diff --git a/e2e/cucumber-features/port-conflict.feature b/e2e/cucumber-features/port-conflict.feature new file mode 100644 index 000000000..aaacdade4 --- /dev/null +++ b/e2e/cucumber-features/port-conflict.feature @@ -0,0 +1,28 @@ +Feature: Report port conflicts + +Background: + Given a compose file + """ + services: + web: + image: nginx + ports: + - 31415:80 + """ + And I run "docker rm -f nginx-pi-31415" + +Scenario: Reports a port allocation conflict with another container + Given I run "docker run -d -p 31415:80 --name nginx-pi-31415 nginx" + When I run "compose up -d" + Then the output contains "port is already allocated" + And the exit code is 1 + +Scenario: Reports a port conflict with some other process + Given a process listening on port 31415 + When I run "compose up -d" + Then the output contains "address already in use" + And the exit code is 1 + +Scenario: Cleanup + Given I run "docker rm -f nginx-pi-31415" + diff --git a/e2e/cucumber-features/ps.feature b/e2e/cucumber-features/ps.feature index e4e256f9d..50917086b 100644 --- a/e2e/cucumber-features/ps.feature +++ b/e2e/cucumber-features/ps.feature @@ -16,6 +16,7 @@ Background: """ FROM golang:1.19-alpine """ + And I run "docker rm -f external-test" Scenario: external container from compose image exists When I run "compose build" @@ -24,4 +25,5 @@ Scenario: external container from compose image exists Then the exit code is 0 And I run "compose ps -a" Then the output does not contain "external-test" + And I run "docker rm -f external-test" diff --git a/e2e/cucumber_test.go b/e2e/cucumber_test.go index 151fba923..6d7cd152e 100644 --- a/e2e/cucumber_test.go +++ b/e2e/cucumber_test.go @@ -19,6 +19,7 @@ package cucumber import ( "context" "fmt" + "net" "os" "path/filepath" "regexp" @@ -87,6 +88,7 @@ func setup(s *godog.ScenarioContext) { s.Step(`output contains "(.*)"$`, th.outputContains(true)) s.Step(`output does not contain "(.*)"$`, th.outputContains(false)) s.Step(`exit code is (\d+)$`, th.exitCodeIs) + s.Step(`a process listening on port (\d+)$`, th.listenerOnPort) } type testHelper struct { @@ -174,3 +176,16 @@ func (th *testHelper) setDockerfile(dockerfileString string) error { } return nil } + +func (th *testHelper) listenerOnPort(port int) error { + l, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) + if err != nil { + return err + } + + th.T.Cleanup(func() { + _ = l.Close() + }) + + return nil +} diff --git a/go.mod b/go.mod index 68ade9d58..6a516d6d2 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/AlecAivazis/survey/v2 v2.3.6 github.com/buger/goterm v1.0.4 - github.com/compose-spec/compose-go v1.13.5 + github.com/compose-spec/compose-go v1.14.0 github.com/containerd/console v1.0.3 github.com/containerd/containerd v1.6.21 github.com/cucumber/godog v0.0.0-00010101000000-000000000000 // replaced; see replace for the actual version used @@ -30,7 +30,7 @@ require ( github.com/sirupsen/logrus v1.9.2 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.4 github.com/theupdateframework/notary v0.7.0 github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 go.opentelemetry.io/otel v1.15.1 @@ -58,7 +58,7 @@ require ( github.com/bugsnag/bugsnag-go v1.5.0 // indirect github.com/cenkalti/backoff/v4 v4.1.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/cloudflare/cfssl v1.4.1 + github.com/cloudflare/cfssl v1.6.4 // indirect github.com/containerd/continuity v0.3.0 // indirect github.com/containerd/ttrpc v1.1.1 // indirect github.com/containerd/typeurl v1.0.2 // indirect @@ -136,7 +136,6 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/zmap/zcrypto v0.0.0-20220605182715-4dfcec6e9a8c // indirect - github.com/zmap/zlint v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.29.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.29.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0 // indirect @@ -149,7 +148,7 @@ require ( go.opentelemetry.io/otel/sdk v1.4.1 // indirect go.opentelemetry.io/otel/trace v1.15.1 // indirect go.opentelemetry.io/proto/otlp v0.12.0 // indirect - golang.org/x/crypto v0.2.0 // indirect + golang.org/x/crypto v0.3.0 // indirect golang.org/x/net v0.7.0 // indirect golang.org/x/oauth2 v0.1.0 // indirect; replaced; see replace for the actual version used golang.org/x/sys v0.5.0 // indirect @@ -166,7 +165,7 @@ require ( k8s.io/api v0.24.1 // indirect; replaced; see replace for the actual version used k8s.io/apimachinery v0.24.1 // indirect; replaced; see replace for the actual version used k8s.io/client-go v0.24.1 // indirect; replaced; see replace for the actual version used - k8s.io/klog/v2 v2.60.1 // indirect + k8s.io/klog/v2 v2.80.1 // indirect k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect sigs.k8s.io/yaml v1.2.0 // indirect diff --git a/go.sum b/go.sum index a9273669c..77d2bb389 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -bitbucket.org/liamstask/goose v0.0.0-20150115234039-8488cc47d90c/go.mod h1:hSVuE3qU7grINVSwrmzHfpg9k87ALBk+XaualNyUzI4= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -74,8 +73,6 @@ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= -github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/hcsshim v0.9.8 h1:lf7xxK2+Ikbj9sVf2QZsouGjRjEp2STj1yDHgoVtU5k= @@ -89,7 +86,6 @@ github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:H github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -139,7 +135,6 @@ github.com/bugsnag/panicwrap v1.2.0 h1:OzrKrRvXis8qEvOkfcxNcYbOd2O7xXS2nnKMEMABF github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/certifi/gocertifi v0.0.0-20180118203423-deb3ae2ef261/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= @@ -150,12 +145,9 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/backoff v0.0.0-20161212185259-647f3cdfc87a/go.mod h1:rzgs2ZOiguV6/NpiDgADjRLPNyZlApIWxKpkT+X8SdY= github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= -github.com/cloudflare/cfssl v1.4.1 h1:vScfU2DrIUI9VPHBVeeAQ0q5A+9yshO1Gz+3QoUQiKw= -github.com/cloudflare/cfssl v1.4.1/go.mod h1:KManx/OJPb5QY+y0+o/898AMcM128sF0bURvoVUSjTo= -github.com/cloudflare/go-metrics v0.0.0-20151117154305-6a9aea36fb41/go.mod h1:eaZPlJWD+G9wseg1BuRXlHnjntPMrywMsyxf+LTOdP4= -github.com/cloudflare/redoctober v0.0.0-20171127175943-746a508df14c/go.mod h1:6Se34jNoqrd8bTxrmJB2Bg2aoZ2CdSXonils9NsiNgo= +github.com/cloudflare/cfssl v1.6.4 h1:NMOvfrEjFfC63K3SGXgAnFdsgkmiq4kATme5BfcqrO8= +github.com/cloudflare/cfssl v1.6.4/go.mod h1:8b3CQMxfWPAeom3zBnGJ6sd+G1NkL5TXqmDXacb+1J0= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -165,8 +157,8 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/compose-spec/compose-go v1.13.5 h1:ogqJOGEbe3uRxMg0ZEufOoCQTpX61l8tUeyW4UQgEBk= -github.com/compose-spec/compose-go v1.13.5/go.mod h1:m0o4G6MQDHjjz9rY7No9FpnNi+9sKic262rzrwuCqic= +github.com/compose-spec/compose-go v1.14.0 h1:/+tQxBEPIrfsi87Qh7/VjMzcJN3BRNER/RO71ku+u6E= +github.com/compose-spec/compose-go v1.14.0/go.mod h1:m0o4G6MQDHjjz9rY7No9FpnNi+9sKic262rzrwuCqic= github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= @@ -195,7 +187,6 @@ github.com/cucumber/messages-go/v16 v16.0.0/go.mod h1:EJcyR5Mm5ZuDsKJnT2N9KRnBK3 github.com/cucumber/messages-go/v16 v16.0.1 h1:fvkpwsLgnIm0qugftrw2YwNlio+ABe2Iu94Ap8GMYIY= github.com/cucumber/messages-go/v16 v16.0.1/go.mod h1:EJcyR5Mm5ZuDsKJnT2N9KRnBK30BGjtYotDKpwQ0v6g= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= -github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -262,7 +253,6 @@ github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4 github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo= github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= -github.com/getsentry/raven-go v0.0.0-20180121060056-563b81fc02b7/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -345,8 +335,7 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= -github.com/google/certificate-transparency-go v1.0.21 h1:Yf1aXowfZ2nuboBsg7iYGLmwsOARdV86pfH3g95wXmE= -github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= +github.com/google/certificate-transparency-go v1.1.4 h1:hCyXHDbtqlr/lMXU0D4WgbalXL0Zk4dSWWMbPV8VrqY= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -453,7 +442,6 @@ github.com/in-toto/in-toto-golang v0.5.0 h1:hb8bgwr0M2hGdDsLjkJ3ZqJ8JFLL/tgYdAxF github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo= github.com/jinzhu/gorm v1.9.11 h1:gaHGvE+UnWGlbWG4Y3FUwY1EcZ5n6S9WtqBA/uySMLE= github.com/jinzhu/gorm v1.9.11/go.mod h1:bu/pK8szGZ2puuErfU0RwyeNdsf3e6nCX/noXaVxkfw= @@ -464,8 +452,7 @@ github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/ github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548/go.mod h1:hGT6jSUVzF6no3QaDSMLGLEHtHSBSefs+MgcDWnmhmo= -github.com/jmoiron/sqlx v0.0.0-20180124204410-05cef0741ade/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU= +github.com/jmoiron/sqlx v1.3.3 h1:j82X0bf7oQ27XeqxicSZsTU5suPwKElg3oyxNn43iTk= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -487,8 +474,6 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kisielk/sqlstruct v0.0.0-20150923205031-648daed35d49/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE= -github.com/kisom/goutils v1.1.0/go.mod h1:+UBTfd78habUYWFbNWTJNG+jNG/i/lGURakr4A/yNRw= github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -504,11 +489,9 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/go-gypsy v0.0.0-20160905020020-08cad365cd28/go.mod h1:T/T7jsxVqf9k/zYOqbgNAsANsjxTd1Yq3htjDhQ1H0c= github.com/laurazard/godog v0.0.0-20220922095256-4c4b17abdae7 h1:R/J7xECY9oHrAg+4QjC38EoXaYysNLzhvXhH/SXcsVc= github.com/laurazard/godog v0.0.0-20220922095256-4c4b17abdae7/go.mod h1:Y02TTpimPXDb70PnG6M3zpODXm1+bjCsuZzcW76xAww= github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v0.0.0-20180201184707-88edab080323/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= @@ -527,7 +510,6 @@ github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -576,7 +558,6 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -710,7 +691,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -719,8 +699,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= @@ -735,13 +715,9 @@ github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6 github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f h1:DLpt6B5oaaS8jyXHa9VA4rrZloBVPVXeCtrOsrFauxc= github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/weppos/publicsuffix-go v0.4.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k= -github.com/weppos/publicsuffix-go v0.5.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k= github.com/weppos/publicsuffix-go v0.15.1-0.20220329081811-9a40b608a236 h1:vMJBP3PQViZsF6cOINtvyMC8ptpLsyJ4EwyFnzuWNxc= github.com/weppos/publicsuffix-go v0.15.1-0.20220329081811-9a40b608a236/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -757,16 +733,11 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE= github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54tB79AMBcySS0R2XIyZBAVmeHranShAFELYx7is= -github.com/zmap/zcrypto v0.0.0-20190729165852-9051775e6a2e/go.mod h1:w7kd3qXHh8FNaczNjslXqvFQiv5mMWRXlL9klTUAHc8= -github.com/zmap/zcrypto v0.0.0-20191112190257-7f2fe6faf8cf/go.mod h1:w7kd3qXHh8FNaczNjslXqvFQiv5mMWRXlL9klTUAHc8= github.com/zmap/zcrypto v0.0.0-20220605182715-4dfcec6e9a8c h1:ufDm/IlBYZYLuiqvQuhpTKwrcAS2OlXEzWbDvTVGbSQ= github.com/zmap/zcrypto v0.0.0-20220605182715-4dfcec6e9a8c/go.mod h1:egdRkzUylATvPkWMpebZbXhv0FMEMJGX/ur0D3Csk2s= -github.com/zmap/zlint v0.0.0-20190806154020-fd021b4cfbeb/go.mod h1:29UiAJNsiVdvTBFCJW8e3q6dcDbOoPkhMgttOSCIMMY= -github.com/zmap/zlint v1.1.0 h1:Vyh2GmprXw5TLmKmkTa2BgFvvYAFBValBFesqkKsszM= -github.com/zmap/zlint v1.1.0/go.mod h1:3MvSF/QhEftzpxKhh3jkBIOvugsSDYMCofl+UaIv0ww= +github.com/zmap/zlint/v3 v3.1.0 h1:WjVytZo79m/L1+/Mlphl09WBob6YTGljN5IGWZFpAv0= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -818,7 +789,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -829,8 +799,8 @@ golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.2.0 h1:BRXPfhNivWL5Yq0BGQ39a2sW6t44aODpfxkWjYdzewE= -golang.org/x/crypto v0.2.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1358,8 +1328,8 @@ k8s.io/client-go v0.22.4/go.mod h1:Yzw4e5e7h1LNHA4uqnMVrpEpUs1hJOiuBsJKIlRCHDA= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc= -k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= +k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc= diff --git a/pkg/api/api.go b/pkg/api/api.go index a31e32e99..f4f730a8f 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -232,6 +232,8 @@ type DownOptions struct { Images string // Volumes remove volumes, both declared in the `volumes` section and anonymous ones Volumes bool + // Services passed in the command line to be stopped + Services []string } // ConfigOptions group options of the Config API diff --git a/pkg/compose/convergence.go b/pkg/compose/convergence.go index eda1b45d2..ca5ade075 100644 --- a/pkg/compose/convergence.go +++ b/pkg/compose/convergence.go @@ -19,6 +19,7 @@ package compose import ( "context" "fmt" + "sort" "strconv" "strings" "sync" @@ -172,6 +173,9 @@ func (c *convergence) ensureService(ctx context.Context, project *types.Project, eg, _ := errgroup.WithContext(ctx) + sort.Slice(containers, func(i, j int) bool { + return containers[i].Created < containers[j].Created + }) for i, container := range containers { if i >= expected { // Scale Down diff --git a/pkg/compose/create.go b/pkg/compose/create.go index bdaff2618..14a3ee8bc 100644 --- a/pkg/compose/create.go +++ b/pkg/compose/create.go @@ -106,11 +106,6 @@ func (s *composeService) create(ctx context.Context, project *types.Project, opt } } - err = prepareServicesDependsOn(project) - if err != nil { - return err - } - return newConvergence(options.Services, observedState, s).apply(ctx, project, options) } @@ -147,72 +142,6 @@ func prepareNetworks(project *types.Project) { } } -func prepareServicesDependsOn(p *types.Project) error { - allServices := types.Project{} - allServices.Services = p.AllServices() - - for i, service := range p.Services { - var dependencies []string - networkDependency := getDependentServiceFromMode(service.NetworkMode) - if networkDependency != "" { - dependencies = append(dependencies, networkDependency) - } - - ipcDependency := getDependentServiceFromMode(service.Ipc) - if ipcDependency != "" { - dependencies = append(dependencies, ipcDependency) - } - - pidDependency := getDependentServiceFromMode(service.Pid) - if pidDependency != "" { - dependencies = append(dependencies, pidDependency) - } - - for _, vol := range service.VolumesFrom { - spec := strings.Split(vol, ":") - if len(spec) == 0 { - continue - } - if spec[0] == "container" { - continue - } - dependencies = append(dependencies, spec[0]) - } - - for _, link := range service.Links { - dependencies = append(dependencies, strings.Split(link, ":")[0]) - } - - for d := range service.DependsOn { - dependencies = append(dependencies, d) - } - - if len(dependencies) == 0 { - continue - } - - // Verify dependencies exist in the project, whether disabled or not - deps, err := allServices.GetServices(dependencies...) - if err != nil { - return err - } - - if service.DependsOn == nil { - service.DependsOn = make(types.DependsOnConfig) - } - - for _, d := range deps { - if _, ok := service.DependsOn[d.Name]; !ok { - service.DependsOn[d.Name] = types.ServiceDependency{ - Condition: types.ServiceConditionStarted, - } - } - } - p.Services[i] = service - } - return nil -} - func (s *composeService) ensureNetworks(ctx context.Context, networks types.Networks) error { for _, network := range networks { err := s.ensureNetwork(ctx, network) @@ -640,8 +569,8 @@ func setLimits(limits *types.Resource, resources *container.Resources) { resources.NanoCPUs = int64(f * 1e9) } } - if limits.PIds > 0 { - resources.PidsLimit = &limits.PIds + if limits.Pids > 0 { + resources.PidsLimit = &limits.Pids } } @@ -743,7 +672,10 @@ func getVolumesFrom(project *types.Project, volumesFrom []string) ([]string, []s } func getDependentServiceFromMode(mode string) string { - if strings.HasPrefix(mode, types.NetworkModeServicePrefix) { + if strings.HasPrefix( + mode, + types.NetworkModeServicePrefix, + ) { return mode[len(types.NetworkModeServicePrefix):] } return "" diff --git a/pkg/compose/dependencies.go b/pkg/compose/dependencies.go index dc09fe0d8..de66f84cd 100644 --- a/pkg/compose/dependencies.go +++ b/pkg/compose/dependencies.go @@ -23,6 +23,8 @@ import ( "sync" "github.com/compose-spec/compose-go/types" + "github.com/docker/compose/v2/pkg/api" + "github.com/pkg/errors" "golang.org/x/sync/errgroup" "github.com/docker/compose/v2/pkg/utils" @@ -38,8 +40,9 @@ const ( ) type graphTraversal struct { - mu sync.Mutex - seen map[string]struct{} + mu sync.Mutex + seen map[string]struct{} + ignored map[string]struct{} extremityNodesFn func(*Graph) []*Vertex // leaves or roots adjacentNodesFn func(*Vertex) []*Vertex // getParents or getChildren @@ -75,7 +78,7 @@ func downDirectionTraversal(visitorFn func(context.Context, string) error) *grap // InDependencyOrder applies the function to the services of the project taking in account the dependency order func InDependencyOrder(ctx context.Context, project *types.Project, fn func(context.Context, string) error, options ...func(*graphTraversal)) error { - graph, err := NewGraph(project.Services, ServiceStopped) + graph, err := NewGraph(project, ServiceStopped) if err != nil { return err } @@ -87,15 +90,46 @@ func InDependencyOrder(ctx context.Context, project *types.Project, fn func(cont } // InReverseDependencyOrder applies the function to the services of the project in reverse order of dependencies -func InReverseDependencyOrder(ctx context.Context, project *types.Project, fn func(context.Context, string) error) error { - graph, err := NewGraph(project.Services, ServiceStarted) +func InReverseDependencyOrder(ctx context.Context, project *types.Project, fn func(context.Context, string) error, options ...func(*graphTraversal)) error { + graph, err := NewGraph(project, ServiceStarted) if err != nil { return err } t := downDirectionTraversal(fn) + for _, option := range options { + option(t) + } return t.visit(ctx, graph) } +func WithRootNodesAndDown(nodes []string) func(*graphTraversal) { + return func(t *graphTraversal) { + if len(nodes) == 0 { + return + } + originalFn := t.extremityNodesFn + t.extremityNodesFn = func(graph *Graph) []*Vertex { + var want []string + for _, node := range nodes { + vertex := graph.Vertices[node] + want = append(want, vertex.Service) + for _, v := range getAncestors(vertex) { + want = append(want, v.Service) + } + } + + t.ignored = map[string]struct{}{} + for k := range graph.Vertices { + if !utils.Contains(want, k) { + t.ignored[k] = struct{}{} + } + } + + return originalFn(graph) + } + } +} + func (t *graphTraversal) visit(ctx context.Context, g *Graph) error { expect := len(g.Vertices) if expect == 0 { @@ -142,7 +176,10 @@ func (t *graphTraversal) run(ctx context.Context, graph *Graph, eg *errgroup.Gro } eg.Go(func() error { - err := t.visitorFn(ctx, node.Service) + var err error + if _, ignore := t.ignored[node.Service]; !ignore { + err = t.visitorFn(ctx, node.Service) + } if err == nil { graph.UpdateStatus(node.Key, t.targetServiceStatus) } @@ -197,6 +234,16 @@ func getChildren(v *Vertex) []*Vertex { return v.GetChildren() } +// getAncestors return all descendents for a vertex, might contain duplicates +func getAncestors(v *Vertex) []*Vertex { + var descendents []*Vertex + for _, parent := range v.GetParents() { + descendents = append(descendents, parent) + descendents = append(descendents, getAncestors(parent)...) + } + return descendents +} + // GetChildren returns a slice with the child vertices of the a Vertex func (v *Vertex) GetChildren() []*Vertex { var res []*Vertex @@ -207,19 +254,28 @@ func (v *Vertex) GetChildren() []*Vertex { } // NewGraph returns the dependency graph of the services -func NewGraph(services types.Services, initialStatus ServiceStatus) (*Graph, error) { +func NewGraph(project *types.Project, initialStatus ServiceStatus) (*Graph, error) { graph := &Graph{ lock: sync.RWMutex{}, Vertices: map[string]*Vertex{}, } - for _, s := range services { + for _, s := range project.Services { graph.AddVertex(s.Name, s.Name, initialStatus) } - for _, s := range services { + for _, s := range project.Services { for _, name := range s.GetDependencies() { - _ = graph.AddEdge(s.Name, name) + err := graph.AddEdge(s.Name, name) + if err != nil { + if api.IsNotFoundError(err) { + ds, err := project.GetDisabledService(name) + if err == nil { + return nil, fmt.Errorf("service %s is required by %s but is disabled. Can be enabled by profiles %s", name, s.Name, ds.Profiles) + } + } + return nil, err + } } } @@ -259,10 +315,10 @@ func (g *Graph) AddEdge(source string, destination string) error { destinationVertex := g.Vertices[destination] if sourceVertex == nil { - return fmt.Errorf("could not find %s", source) + return errors.Wrapf(api.ErrNotFound, "could not find %s", source) } if destinationVertex == nil { - return fmt.Errorf("could not find %s", destination) + return errors.Wrapf(api.ErrNotFound, "could not find %s", destination) } // If they are already connected diff --git a/pkg/compose/dependencies_test.go b/pkg/compose/dependencies_test.go index 1b22cd603..b668f4ada 100644 --- a/pkg/compose/dependencies_test.go +++ b/pkg/compose/dependencies_test.go @@ -19,9 +19,12 @@ package compose import ( "context" "fmt" + "sort" + "sync" "testing" "github.com/compose-spec/compose-go/types" + "github.com/docker/compose/v2/pkg/utils" testify "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gotest.tools/v3/assert" @@ -267,7 +270,7 @@ func TestBuildGraph(t *testing.T) { Services: tC.services, } - graph, err := NewGraph(project.Services, ServiceStopped) + graph, err := NewGraph(&project, ServiceStopped) assert.NilError(t, err, fmt.Sprintf("failed to build graph for: %s", tC.desc)) for k, vertex := range graph.Vertices { @@ -297,3 +300,88 @@ func isVertexEqual(a, b Vertex) bool { childrenEquality && parentEquality } + +func TestWith_RootNodesAndUp(t *testing.T) { + graph := &Graph{ + lock: sync.RWMutex{}, + Vertices: map[string]*Vertex{}, + } + + /** graph topology: + A B + / \ / \ + G C E + \ / + D + | + F + */ + + graph.AddVertex("A", "A", 0) + graph.AddVertex("B", "B", 0) + graph.AddVertex("C", "C", 0) + graph.AddVertex("D", "D", 0) + graph.AddVertex("E", "E", 0) + graph.AddVertex("F", "F", 0) + graph.AddVertex("G", "G", 0) + + _ = graph.AddEdge("C", "A") + _ = graph.AddEdge("C", "B") + _ = graph.AddEdge("E", "B") + _ = graph.AddEdge("D", "C") + _ = graph.AddEdge("D", "E") + _ = graph.AddEdge("F", "D") + _ = graph.AddEdge("G", "A") + + tests := []struct { + name string + nodes []string + want []string + }{ + { + name: "whole graph", + nodes: []string{"A", "B"}, + want: []string{"A", "B", "C", "D", "E", "F", "G"}, + }, + { + name: "only leaves", + nodes: []string{"F", "G"}, + want: []string{"F", "G"}, + }, + { + name: "simple dependent", + nodes: []string{"D"}, + want: []string{"D", "F"}, + }, + { + name: "diamond dependents", + nodes: []string{"B"}, + want: []string{"B", "C", "D", "E", "F"}, + }, + { + name: "partial graph", + nodes: []string{"A"}, + want: []string{"A", "C", "D", "F", "G"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mx := sync.Mutex{} + expected := utils.Set[string]{} + expected.AddAll("C", "G", "D", "F") + var visited []string + + gt := downDirectionTraversal(func(ctx context.Context, s string) error { + mx.Lock() + defer mx.Unlock() + visited = append(visited, s) + return nil + }) + WithRootNodesAndDown(tt.nodes)(gt) + err := gt.visit(context.TODO(), graph) + assert.NilError(t, err) + sort.Strings(visited) + assert.DeepEqual(t, tt.want, visited) + }) + } +} diff --git a/pkg/compose/down.go b/pkg/compose/down.go index 7c4def35a..23ea4e43e 100644 --- a/pkg/compose/down.go +++ b/pkg/compose/down.go @@ -44,7 +44,7 @@ func (s *composeService) Down(ctx context.Context, projectName string, options a }, s.stdinfo()) } -func (s *composeService) down(ctx context.Context, projectName string, options api.DownOptions) error { +func (s *composeService) down(ctx context.Context, projectName string, options api.DownOptions) error { //nolint:gocyclo w := progress.ContextWriter(ctx) resourceToRemove := false @@ -65,6 +65,12 @@ func (s *composeService) down(ctx context.Context, projectName string, options a } } + // Check requested services exists in model + options.Services, err = checkSelectedServices(options, project) + if err != nil { + return err + } + if len(containers) > 0 { resourceToRemove = true } @@ -73,7 +79,7 @@ func (s *composeService) down(ctx context.Context, projectName string, options a serviceContainers := containers.filter(isService(service)) err := s.removeContainers(ctx, w, serviceContainers, options.Timeout, options.Volumes) return err - }) + }, WithRootNodesAndDown(options.Services)) if err != nil { return err } @@ -111,6 +117,23 @@ func (s *composeService) down(ctx context.Context, projectName string, options a return eg.Wait() } +func checkSelectedServices(options api.DownOptions, project *types.Project) ([]string, error) { + var services []string + for _, service := range options.Services { + _, err := project.GetService(service) + if err != nil { + if options.Project != nil { + // ran with an explicit compose.yaml file, so we should not ignore + return nil, err + } + // ran without an explicit compose.yaml file, so can't distinguish typo vs container already removed + } else { + services = append(services, service) + } + } + return services, nil +} + func (s *composeService) ensureVolumesDown(ctx context.Context, project *types.Project, w progress.Writer) []downOp { var ops []downOp for _, vol := range project.Volumes { @@ -229,6 +252,10 @@ func (s *composeService) removeImage(ctx context.Context, image string, w progre w.Event(progress.NewEvent(id, progress.Done, "Removed")) return nil } + if errdefs.IsConflict(err) { + w.Event(progress.NewEvent(id, progress.Warning, "Resource is still in use")) + return nil + } if errdefs.IsNotFound(err) { w.Event(progress.NewEvent(id, progress.Done, "Warning: No resource found to remove")) return nil @@ -244,6 +271,10 @@ func (s *composeService) removeVolume(ctx context.Context, id string, w progress w.Event(progress.NewEvent(resource, progress.Done, "Removed")) return nil } + if errdefs.IsConflict(err) { + w.Event(progress.NewEvent(resource, progress.Warning, "Resource is still in use")) + return nil + } if errdefs.IsNotFound(err) { w.Event(progress.NewEvent(resource, progress.Done, "Warning: No resource found to remove")) return nil diff --git a/pkg/compose/hash.go b/pkg/compose/hash.go index 672af0ffc..c4a4c91a4 100644 --- a/pkg/compose/hash.go +++ b/pkg/compose/hash.go @@ -28,11 +28,12 @@ func ServiceHash(o types.ServiceConfig) (string, error) { // remove the Build config when generating the service hash o.Build = nil o.PullPolicy = "" - o.Scale = 1 - if o.Deploy != nil { - var one uint64 = 1 - o.Deploy.Replicas = &one + if o.Deploy == nil { + o.Deploy = &types.DeployConfig{} } + o.Scale = 1 + var one uint64 = 1 + o.Deploy.Replicas = &one bytes, err := json.Marshal(o) if err != nil { return "", err diff --git a/pkg/compose/secrets.go b/pkg/compose/secrets.go index e3493fa92..581c9c07a 100644 --- a/pkg/compose/secrets.go +++ b/pkg/compose/secrets.go @@ -45,7 +45,7 @@ func (s *composeService) injectSecrets(ctx context.Context, project *types.Proje } err = s.apiClient().CopyToContainer(ctx, id, "/", &b, moby.CopyToContainerOptions{ - CopyUIDGID: true, + CopyUIDGID: config.UID != "" || config.GID != "", }) if err != nil { return err diff --git a/pkg/compose/watch.go b/pkg/compose/watch.go index b57b97b3e..682f14d95 100644 --- a/pkg/compose/watch.go +++ b/pkg/compose/watch.go @@ -130,9 +130,7 @@ func (s *composeService) Watch(ctx context.Context, project *types.Project, serv } name := service.Name - bc := service.Build.Context - - dockerIgnores, err := watch.LoadDockerIgnore(bc) + dockerIgnores, err := watch.LoadDockerIgnore(service.Build.Context) if err != nil { return err } @@ -150,12 +148,17 @@ func (s *composeService) Watch(ctx context.Context, project *types.Project, serv dotGitIgnore, ) - watcher, err := watch.NewWatcher([]string{bc}, ignore) + var paths []string + for _, trigger := range config.Watch { + paths = append(paths, trigger.Path) + } + + watcher, err := watch.NewWatcher(paths, ignore) if err != nil { return err } - fmt.Fprintf(s.stdinfo(), "watching %s\n", bc) + fmt.Fprintf(s.stdinfo(), "watching %s\n", paths) err = watcher.Start() if err != nil { return err diff --git a/pkg/e2e/compose_test.go b/pkg/e2e/compose_test.go index 700856dac..dad8a0d1d 100644 --- a/pkg/e2e/compose_test.go +++ b/pkg/e2e/compose_test.go @@ -102,6 +102,14 @@ func TestLocalComposeUp(t *testing.T) { res.Assert(t, icmd.Expected{Out: `compose-e2e-demo-words-1 gtardif/sentences-api latest`}) }) + t.Run("down SERVICE", func(t *testing.T) { + _ = c.RunDockerComposeCmd(t, "--project-name", projectName, "down", "web") + + res := c.RunDockerComposeCmd(t, "--project-name", projectName, "ps") + assert.Assert(t, !strings.Contains(res.Combined(), "compose-e2e-demo-web-1"), res.Combined()) + assert.Assert(t, strings.Contains(res.Combined(), "compose-e2e-demo-db-1"), res.Combined()) + }) + t.Run("down", func(t *testing.T) { _ = c.RunDockerComposeCmd(t, "--project-name", projectName, "down") }) diff --git a/pkg/e2e/up_test.go b/pkg/e2e/up_test.go index de34d76c2..f2217297b 100644 --- a/pkg/e2e/up_test.go +++ b/pkg/e2e/up_test.go @@ -23,13 +23,14 @@ import ( "context" "os" "os/exec" + "strings" "syscall" "testing" "time" "github.com/docker/compose/v2/pkg/utils" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gotest.tools/v3/assert" "gotest.tools/v3/icmd" ) @@ -79,7 +80,7 @@ func TestUpDependenciesNotStopped(t *testing.T) { defer cancel() cmd, err := StartWithNewGroupID(ctx, testCmd, upOut, nil) - assert.NoError(t, err, "Failed to run compose up") + assert.NilError(t, err, "Failed to run compose up") t.Log("Waiting for containers to be in running state") upOut.RequireEventuallyContains(t, "hello app") @@ -138,3 +139,17 @@ func TestUpWithDependencyExit(t *testing.T) { res.Assert(t, icmd.Expected{ExitCode: 1, Err: "dependency failed to start: container dependencies-db-1 exited (1)"}) }) } + +func TestScaleDoesntRecreate(t *testing.T) { + c := NewCLI(t) + const projectName = "compose-e2e-scale" + t.Cleanup(func() { + c.RunDockerComposeCmd(t, "--project-name", projectName, "down") + }) + + c.RunDockerComposeCmd(t, "-f", "fixtures/simple-composefile/compose.yaml", "--project-name", projectName, "up", "-d") + + res := c.RunDockerComposeCmd(t, "-f", "fixtures/simple-composefile/compose.yaml", "--project-name", projectName, "up", "--scale", "simple=2", "-d") + assert.Check(t, !strings.Contains(res.Combined(), "Recreated")) + +} diff --git a/pkg/progress/event.go b/pkg/progress/event.go index fbb850388..26aca98d8 100644 --- a/pkg/progress/event.go +++ b/pkg/progress/event.go @@ -153,6 +153,15 @@ func RemovedEvent(id string) Event { return NewEvent(id, Done, "Removed") } +// SkippedEvent creates a new Skipped Event +func SkippedEvent(id string, reason string) Event { + return Event{ + ID: id, + Status: Warning, + StatusText: "Skipped: " + reason, + } +} + // NewEvent new event func NewEvent(id string, status EventStatus, statusText string) Event { return Event{ diff --git a/pkg/progress/writer.go b/pkg/progress/writer.go index 422fe2816..14783c1b9 100644 --- a/pkg/progress/writer.go +++ b/pkg/progress/writer.go @@ -21,12 +21,12 @@ import ( "io" "sync" - "github.com/cloudflare/cfssl/log" - "github.com/docker/compose/v2/pkg/api" - "github.com/containerd/console" "github.com/moby/term" + "github.com/sirupsen/logrus" "golang.org/x/sync/errgroup" + + "github.com/docker/compose/v2/pkg/api" ) // Writer can write multiple progress events @@ -125,7 +125,7 @@ func NewWriter(ctx context.Context, out io.Writer, progressTitle string) (Writer } if Mode == ModeTTY { if !isConsole { - log.Warning("Terminal is not a POSIX console") + logrus.Warn("Terminal is not a POSIX console") } else { return newTTYWriter(f, dryRun, progressTitle) } diff --git a/pkg/utils/set.go b/pkg/utils/set.go index c15fcf1a7..e39c81d6f 100644 --- a/pkg/utils/set.go +++ b/pkg/utils/set.go @@ -20,8 +20,18 @@ func (s Set[T]) Add(v T) { s[v] = struct{}{} } -func (s Set[T]) Remove(v T) { - delete(s, v) +func (s Set[T]) AddAll(v ...T) { + for _, e := range v { + s[e] = struct{}{} + } +} + +func (s Set[T]) Remove(v T) bool { + _, ok := s[v] + if ok { + delete(s, v) + } + return ok } func (s Set[T]) Clear() {