From fa60a286b3be1283d2904dd86935d419a1213318 Mon Sep 17 00:00:00 2001 From: Andrew Garner Date: Wed, 17 Dec 2025 10:04:35 -0600 Subject: [PATCH 1/2] spec/integration: remove github.com/ory/dockertest dependency Simplifies the dependency chain for this integration test and avoids a new go vet error observed when bumping to the latest docker libraries. Now this test uses a thin wrapper around the docker cli and does not require a Go docker library + a long tail of transitive dependencies. [TNZ-72735](https://vmw-jira.broadcom.net/browse/TNZ-72735) --- spec/integration/go.mod | 38 +--- spec/integration/go.sum | 92 +--------- spec/integration/internal/docker/docker.go | 196 +++++++++++++++++++++ spec/integration/suite_test.go | 59 +++---- spec/integration/user_management_test.go | 69 +++----- 5 files changed, 255 insertions(+), 199 deletions(-) create mode 100644 spec/integration/internal/docker/docker.go diff --git a/spec/integration/go.mod b/spec/integration/go.mod index bfce29c82..36f14e328 100644 --- a/spec/integration/go.mod +++ b/spec/integration/go.mod @@ -7,49 +7,17 @@ require ( github.com/google/uuid v1.6.0 github.com/onsi/ginkgo/v2 v2.27.3 github.com/onsi/gomega v1.38.3 - github.com/ory/dockertest/v3 v3.12.0 ) require ( - dario.cat/mergo v1.0.2 // indirect filippo.io/edwards25519 v1.1.0 // indirect - github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/Masterminds/semver/v3 v3.4.0 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect - github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/containerd/continuity v0.4.5 // indirect - github.com/containerd/errdefs v1.0.0 // indirect - github.com/containerd/errdefs/pkg v0.3.0 // indirect - github.com/distribution/reference v0.6.0 // indirect - github.com/docker/cli v29.1.2+incompatible // indirect - github.com/docker/go-connections v0.6.0 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.3 // indirect - github.com/go-logr/stdr v1.2.2 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect - github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/pprof v0.0.0-20251208000136-3d256cb9ff16 // indirect - github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/moby/api v1.52.0 // indirect - github.com/moby/moby/client v0.2.1 // indirect - github.com/moby/sys/user v0.4.0 // indirect - github.com/moby/term v0.5.2 // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.1 // indirect - github.com/opencontainers/runc v1.3.3 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect - github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect - github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect - github.com/xeipuuv/gojsonschema v1.2.0 // indirect - go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect - go.opentelemetry.io/otel v1.38.0 // indirect - go.opentelemetry.io/otel/metric v1.38.0 // indirect - go.opentelemetry.io/otel/trace v1.38.0 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect + github.com/stretchr/testify v1.11.1 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/mod v0.30.0 // indirect golang.org/x/net v0.47.0 // indirect @@ -57,5 +25,5 @@ require ( golang.org/x/sys v0.39.0 // indirect golang.org/x/text v0.31.0 // indirect golang.org/x/tools v0.39.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect ) diff --git a/spec/integration/go.sum b/spec/integration/go.sum index 23441bcc4..0bef775f0 100644 --- a/spec/integration/go.sum +++ b/spec/integration/go.sum @@ -1,108 +1,50 @@ -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= -github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= -github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= -github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= -github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= -github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= -github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= -github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= -github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= -github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= -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= -github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= -github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v29.1.2+incompatible h1:s4QI7drXpIo78OM+CwuthPsO5kCf8cpNsck5PsLVTH8= -github.com/docker/cli v29.1.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= -github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs= github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk= github.com/gkampitakis/go-snaps v0.5.15 h1:amyJrvM1D33cPHwVrjo9jQxX8g/7E2wYdZ+01KS3zGE= github.com/gkampitakis/go-snaps v0.5.15/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= -github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/pprof v0.0.0-20251208000136-3d256cb9ff16 h1:ptucaU8cwiAc+/jqDblz0kb1ECLqPTeX/qQym8OBYzY= github.com/google/pprof v0.0.0-20251208000136-3d256cb9ff16/go.mod h1:67FPmZWbr+KDT/VlpWtw6sO9XSjpJmLuHpoLmWiTGgY= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE= github.com/joshdk/go-junit v1.0.0/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +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/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= -github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE= github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A= -github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= -github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/moby/api v1.52.0 h1:00BtlJY4MXkkt84WhUZPRqt5TvPbgig2FZvTbe3igYg= -github.com/moby/moby/api v1.52.0/go.mod h1:8mb+ReTlisw4pS6BRzCMts5M49W5M7bKt1cJy/YbAqc= -github.com/moby/moby/client v0.2.1 h1:1Grh1552mvv6i+sYOdY+xKKVTvzJegcVMhuXocyDz/k= -github.com/moby/moby/client v0.2.1/go.mod h1:O+/tw5d4a1Ha/ZA/tPxIZJapJRUS6LNZ1wiVRxYHyUE= -github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= -github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= -github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= -github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= github.com/onsi/ginkgo/v2 v2.27.3 h1:ICsZJ8JoYafeXFFlFAG75a7CxMsJHwgKwtO+82SE9L8= github.com/onsi/ginkgo/v2 v2.27.3/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/gomega v1.38.3 h1:eTX+W6dobAYfFeGC2PV6RwXRu/MyT+cQguijutvkpSM= github.com/onsi/gomega v1.38.3/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= -github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= -github.com/opencontainers/runc v1.3.3 h1:qlmBbbhu+yY0QM7jqfuat7M1H3/iXjju3VkP9lkFQr4= -github.com/opencontainers/runc v1.3.3/go.mod h1:D7rL72gfWxVs9cJ2/AayxB0Hlvn9g0gaF1R7uunumSI= -github.com/ory/dockertest/v3 v3.12.0 h1:3oV9d0sDzlSQfHtIaB5k6ghUCVMVLpAY8hwrqoCyRCw= -github.com/ory/dockertest/v3 v3.12.0/go.mod h1:aKNDTva3cp8dwOWwb9cWuX84aH5akkxXRvO7KCwWVjE= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= @@ -113,27 +55,6 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= -go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= -go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= -go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= -go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= -go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= -go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= -go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= -go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= -go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= -go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= -go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= @@ -142,8 +63,6 @@ golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= @@ -155,10 +74,5 @@ google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= -gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= -pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= -pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= diff --git a/spec/integration/internal/docker/docker.go b/spec/integration/internal/docker/docker.go new file mode 100644 index 000000000..b888c6230 --- /dev/null +++ b/spec/integration/internal/docker/docker.go @@ -0,0 +1,196 @@ +package docker + +import ( + "bytes" + "database/sql" + "errors" + "fmt" + "io" + "net" + "os/exec" + "strings" + "time" + + "github.com/go-sql-driver/mysql" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +type ContainerSpec struct { + Name string + Image string + Network string + User string + Ports []string + HealthCmd string + HealthInterval string + Env []string + Volumes []string + Entrypoint string + Args []string +} + +func Command(args ...string) (string, error) { + cmd := exec.Command("docker", args...) + out := bytes.Buffer{} + cmd.Stdout = io.MultiWriter(&out, GinkgoWriter) + cmd.Stderr = GinkgoWriter + GinkgoWriter.Println("$", strings.Join(cmd.Args, " ")) + err := cmd.Run() + + return strings.TrimSpace(out.String()), err +} + +func RunContainer(spec ContainerSpec) string { + GinkgoHelper() + + containerID, err := CreateContainer(spec) + Expect(err).NotTo(HaveOccurred(), + `Failed to create docker container: %s`, err) + + DeferCleanup(func() { + _ = RemoveContainer(containerID) + }) + + StartContainer(containerID) + + return containerID +} + +func StartContainer(name string) { + GinkgoHelper() + _, err := Command("start", name) + Expect(err).NotTo(HaveOccurred(), + `Failed to start docker container: %s`, err) +} + +func CreateContainer(spec ContainerSpec) (string, error) { + args := []string{ + "create", + } + + if spec.Name != "" { + args = append(args, "--name="+spec.Name) + } + + if spec.Entrypoint != "" { + args = append(args, "--entrypoint="+spec.Entrypoint) + } + + if spec.Network != "" { + args = append(args, "--network="+spec.Network) + } + + if spec.User != "" { + args = append(args, "--user="+spec.User) + } + + if spec.HealthCmd != "" { + args = append(args, "--health-cmd="+spec.HealthCmd) + } + + if spec.HealthInterval != "" { + args = append(args, "--health-interval="+spec.HealthInterval) + } + + for _, e := range spec.Env { + args = append(args, "--env="+e) + } + + for _, v := range spec.Volumes { + args = append(args, "--volume="+v) + } + + for _, p := range spec.Ports { + args = append(args, "--publish="+p) + } + + args = append(args, spec.Image) + args = append(args, spec.Args...) + + return Command(args...) +} + +func WaitHealthy(container string, timeout time.Duration) error { + timer := time.NewTimer(timeout) + defer timer.Stop() + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + + for { + select { + case <-timer.C: + return errors.New("timeout waiting for healthy container") + case <-ticker.C: + result, err := Command("container", "inspect", "--format={{.State.Status}} {{.State.Health.Status}}", container) + if err != nil { + return fmt.Errorf("error inspecting container: %v", err) + } + + if strings.HasPrefix(result, "exited ") { + return fmt.Errorf("container exited") + } + + if result == "running healthy" { + return nil + } + } + } +} + +func RemoveContainer(name string) error { + _, err := Command("container", "rm", "--force", "--volumes", name) + return err +} + +func RemoveVolume(name string) error { + _, err := Command("volume", "rm", "--force", name) + return err +} + +func ContainerPort(containerID, portSpec string) string { + hostPort, err := Command("container", "port", containerID, portSpec) + Expect(err).NotTo(HaveOccurred(), + `Failed to get container port for container %s and port %s`, containerID, portSpec) + Expect(hostPort).NotTo(BeEmpty()) + + _, port, err := net.SplitHostPort(strings.Fields(hostPort)[0]) + Expect(err).NotTo(HaveOccurred(), + `Error extracting port from host address %s`, hostPort) + + return port +} + +// DSNOpt is a functional option for configuring MySQL database connections. +// Use it to customize connection parameters like username, password, or database. +type DSNOpt func(cfg *mysql.Config) + +func MySQLDB(containerName string, opts ...DSNOpt) *sql.DB { + GinkgoHelper() + + mysqlPort := ContainerPort(containerName, "3306/tcp") + + cfg := &mysql.Config{ + User: "root", + Net: "tcp", + Addr: net.JoinHostPort("127.0.0.1", mysqlPort), + InterpolateParams: true, + AllowNativePasswords: true, + } + + for _, opt := range opts { + opt(cfg) + } + + connector, err := mysql.NewConnector(cfg) + Expect(err).NotTo(HaveOccurred()) + + return sql.OpenDB(connector) +} + +func WithUsernamePassword(username, password string) DSNOpt { + return func(cfg *mysql.Config) { + cfg.User = username + cfg.Passwd = password + } +} diff --git a/spec/integration/suite_test.go b/spec/integration/suite_test.go index a2dd5835f..08279e2af 100644 --- a/spec/integration/suite_test.go +++ b/spec/integration/suite_test.go @@ -1,16 +1,16 @@ package integration_test import ( - "database/sql" - "fmt" "log" "testing" + "time" "github.com/go-sql-driver/mysql" "github.com/google/uuid" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/ory/dockertest/v3" + + "integration/internal/docker" ) func TestUserManagement(t *testing.T) { @@ -19,45 +19,34 @@ func TestUserManagement(t *testing.T) { } var ( - pool *dockertest.Pool volumeID string ) var _ = BeforeSuite(func() { Expect(mysql.SetLogger(log.New(GinkgoWriter, log.Prefix(), log.Flags()))).To(Succeed()) - - var err error - pool, err = dockertest.NewPool("") - Expect(err).NotTo(HaveOccurred()) - volumeID = uuid.New().String() }) -func startMySQL(tag string, mysqlOptions []string, extraMounts []string) (*dockertest.Resource, error) { - resource, err := pool.RunWithOptions(&dockertest.RunOptions{ - Repository: "percona/percona-xtradb-cluster", - Tag: tag, - Cmd: append([]string{ - "--pxc-maint-transition-period=0", - "--log-error-verbosity=3", - "--innodb-flush-method=fsync", - }, mysqlOptions...), - Env: []string{"PXC_CLUSTER_NAME=testcluster", "MYSQL_ALLOW_EMPTY_PASSWORD=1"}, - Mounts: append([]string{volumeID + ":/var/lib/mysql"}, extraMounts...), - ExposedPorts: []string{"3306/tcp"}, +func startMySQL(tag string, mysqlOptions []string, extraMounts []string) (containerID string) { + GinkgoHelper() + + containerArgs := append([]string{ + "--pxc-maint-transition-period=0", + "--log-error-verbosity=3", + "--innodb-flush-method=fsync", + }, mysqlOptions...) + + containerID = docker.RunContainer(docker.ContainerSpec{ + Image: "percona/percona-xtradb-cluster:" + tag, + Args: containerArgs, + Env: []string{"PXC_CLUSTER_NAME=testcluster", "MYSQL_ALLOW_EMPTY_PASSWORD=1"}, + Volumes: append([]string{volumeID + ":/var/lib/mysql"}, extraMounts...), + Ports: []string{"3306/tcp"}, + HealthCmd: "mysqladmin -u root --host=127.0.0.1 ping", + HealthInterval: "2s", }) - if err != nil { - return nil, err - } - - db, err := sql.Open("mysql", fmt.Sprintf("root@(localhost:%s)/mysql", resource.GetPort("3306/tcp"))) - if err != nil { - resource.Close() - return nil, err - } - defer func(db *sql.DB) { - _ = db.Close() - }(db) - - return resource, pool.Retry(db.Ping) + + Expect(docker.WaitHealthy(containerID, 5*time.Minute)).To(Succeed()) + + return containerID } diff --git a/spec/integration/user_management_test.go b/spec/integration/user_management_test.go index 86e6735aa..a8a2e0f63 100644 --- a/spec/integration/user_management_test.go +++ b/spec/integration/user_management_test.go @@ -4,7 +4,6 @@ import ( "bytes" "database/sql" "encoding/json" - "fmt" "os" "os/exec" "strings" @@ -12,8 +11,8 @@ import ( "github.com/google/uuid" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/ory/dockertest/v3" - "github.com/ory/dockertest/v3/docker" + + "integration/internal/docker" ) type UserRole struct { @@ -40,7 +39,7 @@ type MySQLJobSpec struct { var _ = Describe("UserManagement", Ordered, func() { var ( dbUsers MySQLJobSpec - resource *dockertest.Resource + resource string mysqlVersionTag string ) @@ -66,30 +65,27 @@ var _ = Describe("UserManagement", Ordered, func() { Expect(cmd.Run()).To(Succeed()) // Initialize the data volume first, so our db_init does not interfere with percona's entrypoint bootstrapping - resource, err = startMySQL(mysqlVersionTag, nil, nil) - Expect(err).NotTo(HaveOccurred()) - Expect(resource.Close()).To(Succeed()) + resource = startMySQL(mysqlVersionTag, nil, nil) + Expect(docker.RemoveContainer(resource)).To(Succeed()) - resource, err = startMySQL( + resource = startMySQL( mysqlVersionTag, []string{"--init-file=/db_init"}, []string{f.Name() + ":/db_init"}, ) - Expect(err).NotTo(HaveOccurred()) - }) + DeferCleanup(func() { + if CurrentSpecReport().Failed() { + return + } - AfterEach(func() { - if CurrentSpecReport().Failed() { - return - } - Expect(pool.Purge(resource)).To(Succeed()) - Expect(pool.Client.RemoveVolumeWithOptions(docker.RemoveVolumeOptions{ - Name: volumeID, - Force: true, - })).To(Succeed()) + Expect(docker.RemoveContainer(resource)).To(Succeed()) + Expect(docker.RemoveVolume(volumeID)).To(Succeed()) + }) }) showGrants := func(db *sql.DB, username, host string) (grants []string) { + GinkgoHelper() + rows, err := db.Query(`SHOW GRANTS FOR ?@?`, username, host) Expect(err).NotTo(HaveOccurred()) for rows.Next() { @@ -102,6 +98,8 @@ var _ = Describe("UserManagement", Ordered, func() { } showSchemas := func(db *sql.DB, username, host string) (schemas []string) { + GinkgoHelper() + rows, err := db.Query(`SHOW SCHEMAS`) Expect(err).NotTo(HaveOccurred()) for rows.Next() { @@ -115,28 +113,22 @@ var _ = Describe("UserManagement", Ordered, func() { // verifyUser proves that a given username:password credential can connect to a given schema and has the expected permissions verifyUser := func(username, password, schema string, expectedGrants []string) { - db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@(localhost:%s)/%s?interpolateParams=true", - username, password, resource.GetPort("3306/tcp"), schema)) - Expect(err).NotTo(HaveOccurred()) + db := docker.MySQLDB(resource, docker.WithUsernamePassword(username, password)) defer db.Close() Expect(showGrants(db, username, "%")).To(ConsistOf(expectedGrants)) } verifyGrantsForLocalUser := func(username, password string, expectedGrants []string) { - dsn := fmt.Sprintf("root@(localhost:%s)/?interpolateParams=true", resource.GetPort("3306/tcp")) - db, err := sql.Open("mysql", dsn) - Expect(err).NotTo(HaveOccurred()) + db := docker.MySQLDB(resource) defer db.Close() Expect(showGrants(db, username, "localhost")).To(ConsistOf(expectedGrants)) } verifySchemasForLocalUser := func(username, password string, expectedSchemas []string) { - dsn := fmt.Sprintf("root@(localhost:%s)/?interpolateParams=true", resource.GetPort("3306/tcp")) - db, err := sql.Open("mysql", dsn) + db := docker.MySQLDB(resource) defer db.Close() // TODO: check other helpers for Close() calls. - Expect(err).NotTo(HaveOccurred()) Expect(showSchemas(db, username, "localhost")).To(ContainElements(expectedSchemas)) } @@ -190,7 +182,7 @@ var _ = Describe("UserManagement", Ordered, func() { verifyLocalUser := func(username, password string) { var out bytes.Buffer cmd := exec.Command("docker", - "exec", resource.Container.ID, + "exec", resource, "mysql", "--user="+username, "--password="+password, @@ -202,9 +194,7 @@ var _ = Describe("UserManagement", Ordered, func() { } verifyMaxUserConnections := func(username, host string, expectedValue int) { - db, err := sql.Open("mysql", fmt.Sprintf("root@(localhost:%s)/mysql?interpolateParams=true", - resource.GetPort("3306/tcp"))) - Expect(err).NotTo(HaveOccurred()) + db := docker.MySQLDB(resource) defer db.Close() var actualMaxUserConnections int @@ -216,12 +206,13 @@ var _ = Describe("UserManagement", Ordered, func() { } verifyLocalAdminUser := func(username, password string) { - db, err := sql.Open("mysql", fmt.Sprintf("root@(localhost:%s)/mysql?interpolateParams=true", - resource.GetPort("3306/tcp"))) - Expect(err).NotTo(HaveOccurred()) + db := docker.MySQLDB(resource) defer db.Close() - var expectedPrivileges []string + var ( + expectedPrivileges []string + err error + ) if mysqlVersionTag == "5.7" { expectedPrivileges = []string{"GRANT OPTION", "ALL PRIVILEGES", "PROXY", "USAGE"} } else { @@ -237,7 +228,7 @@ var _ = Describe("UserManagement", Ordered, func() { // Validate the admin user can actually log in. I.e. we set credentials correctly cmd := exec.Command("docker", - "exec", resource.Container.ID, + "exec", resource, "mysql", "--user="+username, "--password="+password, @@ -248,9 +239,7 @@ var _ = Describe("UserManagement", Ordered, func() { } verifyUserFunc := func(username, password string, cb func(db *sql.DB)) { - db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@(localhost:%s)/?interpolateParams=true", - username, password, resource.GetPort("3306/tcp"))) - Expect(err).NotTo(HaveOccurred()) + db := docker.MySQLDB(resource, docker.WithUsernamePassword(username, password)) defer db.Close() cb(db) } From 404db305fafc6815d5758ec90d3445520c224124 Mon Sep 17 00:00:00 2001 From: Kim Bassett Date: Tue, 30 Dec 2025 15:40:09 -0800 Subject: [PATCH 2/2] spec/integration: Adjust 5.7 docker test healthchecks percona 5.7 docker images don't contain "mysqladmin" tool used by 8.x healthchecks, so special-case an alternate. [TNZ-72735](https://vmw-jira.broadcom.net/browse/TNZ-72735) Authored-by: Kim Bassett --- spec/integration/suite_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/integration/suite_test.go b/spec/integration/suite_test.go index 08279e2af..8e5d65464 100644 --- a/spec/integration/suite_test.go +++ b/spec/integration/suite_test.go @@ -42,7 +42,7 @@ func startMySQL(tag string, mysqlOptions []string, extraMounts []string) (contai Env: []string{"PXC_CLUSTER_NAME=testcluster", "MYSQL_ALLOW_EMPTY_PASSWORD=1"}, Volumes: append([]string{volumeID + ":/var/lib/mysql"}, extraMounts...), Ports: []string{"3306/tcp"}, - HealthCmd: "mysqladmin -u root --host=127.0.0.1 ping", + HealthCmd: `mysql --user=root --host=127.0.0.1 --execute="SELECT 1"`, HealthInterval: "2s", })