From 6f2f66133c166f9734651b506daf041a944614fe Mon Sep 17 00:00:00 2001 From: Andrew Ferrazzutti Date: Sun, 2 Aug 2026 22:35:50 -0400 Subject: [PATCH 1/3] Migrate docker module to moby Migrate from the deprecated github.com/docker/docker module to the current latest version of github.com/moby/moby, and make all changes necessary to adapt to its refactoring. --- CONTRIBUTING.md | 2 +- cmd/perftest/snapshot.go | 2 +- go.mod | 21 ++--- go.sum | 72 ++++------------ internal/docker/builder.go | 135 ++++++++++++++++-------------- internal/docker/deployer.go | 160 +++++++++++++++++++----------------- internal/docker/labels.go | 6 +- runtime/hs.go | 9 +- runtime/hs_dendrite.go | 5 +- 9 files changed, 193 insertions(+), 219 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0e5ea0e5..6c9dc358 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ We ask that everybody who contributes to this project signs off their contributi We follow a simple 'inbound=outbound' model for contributions: the act of submitting an 'inbound' contribution means that the contributor agrees to license their contribution under the same terms as the project's overall 'outbound' license - in our case, this is Apache Software License v2 (see [LICENSE](./LICENSE)). -In order to have a concrete record that your contribution is intentional and you agree to license it under the same terms as the project's license, we've adopted the same lightweight approach used by the [Linux Kernel](https://www.kernel.org/doc/html/latest/process/submitting-patches.html), [Docker](https://github.com/docker/docker/blob/master/CONTRIBUTING.md), and many other projects: the [Developer Certificate of Origin](https://developercertificate.org/) (DCO). This is a simple declaration that you wrote the contribution or otherwise have the right to contribute it to Matrix: +In order to have a concrete record that your contribution is intentional and you agree to license it under the same terms as the project's license, we've adopted the same lightweight approach used by the [Linux Kernel](https://www.kernel.org/doc/html/latest/process/submitting-patches.html), [Docker](https://github.com/moby/moby/blob/master/CONTRIBUTING.md), and many other projects: the [Developer Certificate of Origin](https://developercertificate.org/) (DCO). This is a simple declaration that you wrote the contribution or otherwise have the right to contribute it to Matrix: ``` Developer Certificate of Origin diff --git a/cmd/perftest/snapshot.go b/cmd/perftest/snapshot.go index 3294ee06..ef9b2892 100644 --- a/cmd/perftest/snapshot.go +++ b/cmd/perftest/snapshot.go @@ -5,8 +5,8 @@ import ( "encoding/json" "time" - "github.com/docker/docker/api/types/container" "github.com/matrix-org/complement/internal/docker" + "github.com/moby/moby/api/types/container" ) type Snapshot struct { diff --git a/go.mod b/go.mod index f98df2f8..fec5f3bc 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,12 @@ module github.com/matrix-org/complement go 1.25.0 require ( - github.com/docker/docker v28.5.2+incompatible - github.com/docker/go-connections v0.7.0 github.com/gorilla/mux v1.8.1 github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 github.com/matrix-org/gomatrixserverlib v0.0.0-20260506075950-c9c468727353 github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 + github.com/moby/moby/api v1.55.0 + github.com/moby/moby/client v0.5.1 github.com/sirupsen/logrus v1.9.4 github.com/tidwall/gjson v1.19.0 github.com/tidwall/sjson v1.2.5 @@ -22,41 +22,34 @@ require ( codeberg.org/go-latex/latex v0.2.0 // indirect codeberg.org/go-pdf/fpdf v0.11.1 // indirect git.sr.ht/~sbinet/gg v0.7.0 // indirect - github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect - github.com/containerd/log v0.1.0 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/go-units v0.4.0 // indirect + github.com/docker/go-connections v0.7.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/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/hashicorp/go-set/v3 v3.0.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/sys/atomicwriter v0.1.0 // indirect - github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect - github.com/morikuni/aec v1.0.0 // indirect github.com/oleiade/lane/v2 v2.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect - github.com/pkg/errors v0.9.1 // indirect + github.com/opencontainers/image-spec v1.1.1 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect go.opentelemetry.io/otel v1.43.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 // indirect go.opentelemetry.io/otel/metric v1.43.0 // indirect go.opentelemetry.io/otel/sdk v1.43.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go.opentelemetry.io/otel/trace v1.43.0 // indirect golang.org/x/image v0.41.0 // indirect golang.org/x/sys v0.46.0 // indirect golang.org/x/text v0.38.0 // indirect - golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect gonum.org/v1/gonum v0.17.0 // indirect - gotest.tools/v3 v3.0.3 // indirect ) diff --git a/go.sum b/go.sum index 3dd402e8..93a3d7cd 100644 --- a/go.sum +++ b/go.sum @@ -12,9 +12,6 @@ git.sr.ht/~sbinet/cmpimg v0.1.0 h1:E0zPRk2muWuCqSKSVZIWsgtU9pjsw3eKHi8VmQeScxo= git.sr.ht/~sbinet/cmpimg v0.1.0/go.mod h1:FU12psLbF4TfNXkKH2ZZQ29crIqoiqTZmeQ7dkp/pxE= git.sr.ht/~sbinet/gg v0.7.0 h1:YmNf7YKd7diDMTPm86hZa1EM3pbkOyD/zzjl0LZUdNM= git.sr.ht/~sbinet/gg v0.7.0/go.mod h1:VYeli15tpMM4EvqlivlVbbyvWZlOU+EZn4XZmfBGUdM= -github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= @@ -22,27 +19,20 @@ github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw= github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= -github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= -github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 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/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= -github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM= -github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c= github.com/docker/go-connections v0.7.0/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +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/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -52,16 +42,12 @@ 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/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/hashicorp/go-set/v3 v3.0.0 h1:CaJBQvQCOWoftrBcDt7Nwgo0kdpmrKxar/x2o6pV9JA= @@ -77,30 +63,22 @@ github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE= github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE= 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/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= -github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= -github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= -github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= -github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 h1:yH0SvLzcbZxcJXho2yh7CqdENGMQe73Cw3woZBpPli0= -github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/moby/moby/api v1.55.0 h1:2/sexvQyqIWS8pRSCFddBfpW2qE7vR7FCL+vN8pxwMc= +github.com/moby/moby/api v1.55.0/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= +github.com/moby/moby/client v0.5.1 h1:tYNaJno4c0HXz12y5BiqEDy0rVTYkWzI26lGvnTMiJw= +github.com/moby/moby/client v0.5.1/go.mod h1:odLstlZ6uSnfvAgVxMpvgmb8SUdd+siH2T0GBuxVAlM= github.com/oleiade/lane/v2 v2.0.0 h1:XW/ex/Inr+bPkLd3O240xrFOhUkTd4Wy176+Gv0E3Qw= github.com/oleiade/lane/v2 v2.0.0/go.mod h1:i5FBPFAYSWCgLh58UkUGCChjcCzef/MI7PlQm2TKCeg= 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.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/shoenig/test v1.11.0 h1:NoPa5GIoBwuqzIviCrnUJa+t5Xb4xi5Z+zODJnIDsEQ= github.com/shoenig/test v1.11.0/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsBHFoI= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 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.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= @@ -116,22 +94,18 @@ github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 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.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak= go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= -go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= -go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -144,7 +118,6 @@ golang.org/x/image v0.41.0/go.mod h1:uIc348UZMSvS5Z65CVZ7iDPaNobNFEPeJ4kbqTOszmA golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -156,49 +129,36 @@ golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE= golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8= golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= gonum.org/v1/plot v0.17.0 h1:d0DwPVBe9jnEGqQBoZGl/P2M9WciJbG2CnV59C9QBT4= gonum.org/v1/plot v0.17.0/go.mod h1:ipt2GUN1oqzr2O7wCjLDtw1ShfIYYNBp4o0O1Ez5B3Y= -google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA= -google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= -google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= -google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= -google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY= gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 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.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= +gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= +pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/internal/docker/builder.go b/internal/docker/builder.go index 8b0edc99..82145212 100644 --- a/internal/docker/builder.go +++ b/internal/docker/builder.go @@ -17,15 +17,14 @@ import ( "context" "fmt" "log" + "net/netip" "strings" "time" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/client" - "github.com/docker/docker/pkg/stdcopy" - "github.com/docker/go-connections/nat" + "github.com/moby/moby/api/pkg/stdcopy" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/network" + "github.com/moby/moby/client" "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/config" @@ -77,7 +76,7 @@ func (d *Builder) Cleanup() { // removeImages removes all images with `complementLabel`. func (d *Builder) removeNetworks() error { - networks, err := d.Docker.NetworkList(context.Background(), network.ListOptions{ + networks, err := d.Docker.NetworkList(context.Background(), client.NetworkListOptions{ Filters: label( complementLabel, "complement_pkg="+d.Config.PackageNamespace, @@ -86,8 +85,8 @@ func (d *Builder) removeNetworks() error { if err != nil { return err } - for _, nw := range networks { - err = d.Docker.NetworkRemove(context.Background(), nw.ID) + for _, nw := range networks.Items { + _, err = d.Docker.NetworkRemove(context.Background(), nw.ID, client.NetworkRemoveOptions{}) if err != nil { return err } @@ -97,7 +96,7 @@ func (d *Builder) removeNetworks() error { // removeImages removes all images with `complementLabel`. func (d *Builder) removeImages() error { - images, err := d.Docker.ImageList(context.Background(), image.ListOptions{ + images, err := d.Docker.ImageList(context.Background(), client.ImageListOptions{ Filters: label( complementLabel, "complement_pkg="+d.Config.PackageNamespace, @@ -106,7 +105,7 @@ func (d *Builder) removeImages() error { if err != nil { return err } - for _, img := range images { + for _, img := range images.Items { // we only clean up localhost/complement images else if someone docker pulls // an anonymous snapshot we might incorrectly nuke it :( any non-localhost // tag marks this image as safe (as images can have multiple tags) @@ -133,7 +132,7 @@ func (d *Builder) removeImages() error { d.log("Keeping image created from blueprint %s", bprintName) continue } - _, err = d.Docker.ImageRemove(context.Background(), img.ID, image.RemoveOptions{ + _, err = d.Docker.ImageRemove(context.Background(), img.ID, client.ImageRemoveOptions{ Force: true, }) if err != nil { @@ -146,7 +145,7 @@ func (d *Builder) removeImages() error { // removeContainers removes all containers with `complementLabel`. func (d *Builder) removeContainers() error { - containers, err := d.Docker.ContainerList(context.Background(), container.ListOptions{ + containers, err := d.Docker.ContainerList(context.Background(), client.ContainerListOptions{ All: true, Filters: label( complementLabel, @@ -156,8 +155,8 @@ func (d *Builder) removeContainers() error { if err != nil { return err } - for _, c := range containers { - err = d.Docker.ContainerRemove(context.Background(), c.ID, container.RemoveOptions{ + for _, c := range containers.Items { + _, err = d.Docker.ContainerRemove(context.Background(), c.ID, client.ContainerRemoveOptions{ Force: true, }) if err != nil { @@ -168,7 +167,7 @@ func (d *Builder) removeContainers() error { } func (d *Builder) ConstructBlueprintIfNotExist(bprint b.Blueprint) error { - images, err := d.Docker.ImageList(context.Background(), image.ListOptions{ + images, err := d.Docker.ImageList(context.Background(), client.ImageListOptions{ Filters: label( "complement_blueprint="+bprint.Name, "complement_pkg="+d.Config.PackageNamespace, @@ -177,7 +176,7 @@ func (d *Builder) ConstructBlueprintIfNotExist(bprint b.Blueprint) error { if err != nil { return fmt.Errorf("ConstructBlueprintIfNotExist(%s): failed to ImageList: %w", bprint.Name, err) } - if len(images) == 0 { + if len(images.Items) == 0 { err = d.ConstructBlueprint(bprint) if err != nil { return fmt.Errorf("ConstructBlueprintIfNotExist(%s): failed to ConstructBlueprint: %w", bprint.Name, err) @@ -197,12 +196,12 @@ func (d *Builder) ConstructBlueprint(bprint b.Blueprint) error { // wait a bit for images/containers to show up in 'image ls' foundImages := false - var images []image.Summary + var images client.ImageListResult var err error waitTime := 5 * time.Second startTime := time.Now() for time.Since(startTime) < waitTime { - images, err = d.Docker.ImageList(context.Background(), image.ListOptions{ + images, err = d.Docker.ImageList(context.Background(), client.ImageListOptions{ Filters: label( complementLabel, "complement_blueprint="+bprint.Name, @@ -212,7 +211,7 @@ func (d *Builder) ConstructBlueprint(bprint b.Blueprint) error { if err != nil { return err } - if len(images) < len(bprint.Homeservers) { + if len(images.Items) < len(bprint.Homeservers) { time.Sleep(100 * time.Millisecond) } else { foundImages = true @@ -226,7 +225,7 @@ func (d *Builder) ConstructBlueprint(bprint b.Blueprint) error { return fmt.Errorf("failed to find built images via ImageList: did they all build ok?") } var imgDatas []string - for _, img := range images { + for _, img := range images.Items { imgDatas = append(imgDatas, fmt.Sprintf("%s=>%v", img.ID, img.Labels)) } d.log("Constructed blueprint '%s' : %v", bprint.Name, imgDatas) @@ -252,7 +251,7 @@ func (d *Builder) construct(bprint b.Blueprint) (errs []error) { // something went wrong, but we have a container which may have interesting logs printLogs(d.Docker, res.containerID, res.contextStr) } - if delErr := d.Docker.ContainerRemove(context.Background(), res.containerID, container.RemoveOptions{ + if _, delErr := d.Docker.ContainerRemove(context.Background(), res.containerID, client.ContainerRemoveOptions{ Force: true, }); delErr != nil { d.log("%s: failed to remove container which failed to deploy: %s", res.contextStr, delErr) @@ -262,19 +261,21 @@ func (d *Builder) construct(bprint b.Blueprint) (errs []error) { } // kill the container defer func(r result) { - containerInfo, err := d.Docker.ContainerInspect(context.Background(), r.containerID) + containerInfo, err := d.Docker.ContainerInspect(context.Background(), r.containerID, client.ContainerInspectOptions{}) if err != nil { d.log("%s : Can't get status of %s", r.contextStr, r.containerID) return } - if !containerInfo.State.Running { + if !containerInfo.Container.State.Running { // The container isn't running anyway, so no need to kill it. return } - killErr := d.Docker.ContainerKill(context.Background(), r.containerID, "KILL") + _, killErr := d.Docker.ContainerKill(context.Background(), r.containerID, client.ContainerKillOptions{ + Signal: "SIGKILL", + }) if killErr != nil { d.log("%s : Failed to kill container %s: %s\n", r.contextStr, r.containerID, killErr) } @@ -323,7 +324,7 @@ func (d *Builder) construct(bprint b.Blueprint) (errs []error) { // then incurs a slow recovery process when we use the blueprint later. d.log("%s: Stopping container: %s", res.contextStr, res.containerID) tenSeconds := 10 - d.Docker.ContainerStop(context.Background(), res.containerID, container.StopOptions{ + d.Docker.ContainerStop(context.Background(), res.containerID, client.ContainerStopOptions{ Timeout: &tenSeconds, }) @@ -331,9 +332,9 @@ func (d *Builder) construct(bprint b.Blueprint) (errs []error) { d.log("%s: Stopped container: %s", res.contextStr, res.containerID) // commit the container - commit, err := d.Docker.ContainerCommit(context.Background(), res.containerID, container.CommitOptions{ + commit, err := d.Docker.ContainerCommit(context.Background(), res.containerID, client.ContainerCommitOptions{ Author: "Complement", - Pause: true, + NoPause: false, Reference: "localhost/complement:" + res.contextStr, Changes: toChanges(labels), @@ -438,7 +439,7 @@ func generateASRegistrationYaml(as b.ApplicationService) string { // Name is guaranteed not to be empty when err == nil func createNetworkIfNotExists(docker *client.Client, pkgNamespace, blueprintName string) (networkName string, err error) { // check if a network already exists for this blueprint - nws, err := docker.NetworkList(context.Background(), network.ListOptions{ + nws, err := docker.NetworkList(context.Background(), client.NetworkListOptions{ Filters: label( "complement_pkg="+pkgNamespace, "complement_blueprint="+blueprintName, @@ -448,15 +449,15 @@ func createNetworkIfNotExists(docker *client.Client, pkgNamespace, blueprintName return "", fmt.Errorf("%s: failed to list networks. %w", blueprintName, err) } // return the existing network - if len(nws) > 0 { - if len(nws) > 1 { - log.Printf("WARNING: createNetworkIfNotExists got %d networks for pkg=%s blueprint=%s", len(nws), pkgNamespace, blueprintName) + if len(nws.Items) > 0 { + if len(nws.Items) > 1 { + log.Printf("WARNING: createNetworkIfNotExists got %d networks for pkg=%s blueprint=%s", len(nws.Items), pkgNamespace, blueprintName) } - return nws[0].Name, nil + return nws.Items[0].Name, nil } networkName = "complement_" + pkgNamespace + "_" + blueprintName // make a user-defined network so we get DNS based on the container name - nw, err := docker.NetworkCreate(context.Background(), networkName, network.CreateOptions{ + nw, err := docker.NetworkCreate(context.Background(), networkName, client.NetworkCreateOptions{ Labels: map[string]string{ complementLabel: blueprintName, "complement_blueprint": blueprintName, @@ -466,11 +467,11 @@ func createNetworkIfNotExists(docker *client.Client, pkgNamespace, blueprintName if err != nil { return "", fmt.Errorf("%s: failed to create docker network. %w", blueprintName, err) } - if nw.Warning != "" { + if len(nw.Warning) > 0 && nw.Warning[0] != "" { if nw.ID == "" { - return "", fmt.Errorf("%s: fatal warning while creating docker network. %s", blueprintName, nw.Warning) + return "", fmt.Errorf("%s: fatal warning while creating docker network. %s", blueprintName, nw.Warning[0]) } - log.Printf("WARNING: %s\n", nw.Warning) + log.Printf("WARNING: %s\n", nw.Warning[0]) } if nw.ID == "" { return "", fmt.Errorf("%s: unexpected empty ID while creating networkID", blueprintName) @@ -479,7 +480,7 @@ func createNetworkIfNotExists(docker *client.Client, pkgNamespace, blueprintName } func printLogs(docker *client.Client, containerID, contextStr string) { - reader, err := docker.ContainerLogs(context.Background(), containerID, container.LogsOptions{ + reader, err := docker.ContainerLogs(context.Background(), containerID, client.ContainerLogsOptions{ ShowStderr: true, ShowStdout: true, Follow: false, @@ -497,7 +498,7 @@ func printLogs(docker *client.Client, containerID, contextStr string) { func printPortBindingsOfAllComplementContainers(docker *client.Client, contextStr string) { ctx := context.Background() - containers, err := docker.ContainerList(ctx, container.ListOptions{ + containers, err := docker.ContainerList(ctx, client.ContainerListOptions{ All: true, Filters: label( complementLabel, @@ -510,10 +511,10 @@ func printPortBindingsOfAllComplementContainers(docker *client.Client, contextSt log.Printf("============== %s : START ALL COMPLEMENT DOCKER PORT BINDINGS ==============\n", contextStr) - for _, container := range containers { + for _, container := range containers.Items { log.Printf("Container: %s: %s", container.ID, container.Names) - inspectRes, err := docker.ContainerInspect(ctx, container.ID) + inspectRes, err := docker.ContainerInspect(ctx, container.ID, client.ContainerInspectOptions{}) if err != nil { log.Printf("%s : Failed to inspect container (%s) while trying to `printPortBindingsOfAllComplementContainers`: %s\n", contextStr, container.ID, err) return @@ -522,7 +523,7 @@ func printPortBindingsOfAllComplementContainers(docker *client.Client, contextSt // Print an example so it's easier to understand the output log.Printf(" (host) -> (container)\n") // Then print the actual port bindings - for containerPort, portBindings := range inspectRes.NetworkSettings.Ports { + for containerPort, portBindings := range inspectRes.Container.NetworkSettings.Ports { hostPortBindingStrings := make([]string, len(portBindings)) for portBindingIndex, portBinding := range portBindings { hostPortBindingStrings[portBindingIndex] = fmt.Sprintf("%s:%s", portBinding.HostIP, portBinding.HostPort) @@ -537,58 +538,68 @@ func printPortBindingsOfAllComplementContainers(docker *client.Client, contextSt } // endpoints transforms the homeserver ports into the base URL and federation base URL. -func endpoints(p nat.PortMap, hsPortBindingIP string, csPort, ssPort int) (baseURL, fedBaseURL string, err error) { +func endpoints(p network.PortMap, hsPortBindingIP string, csPort, ssPort int) (baseURL, fedBaseURL string, err error) { csapiPortBinding, err := findPortBinding(p, hsPortBindingIP, csPort) if err != nil { return "", "", fmt.Errorf("Problem finding CS API port: %s", err) } - baseURL = fmt.Sprintf("http://"+csapiPortBinding.HostIP+":%s", csapiPortBinding.HostPort) + baseURL = fmt.Sprintf("http://%s:%s", csapiPortBinding.HostIP, csapiPortBinding.HostPort) ssapiPortBinding, err := findPortBinding(p, hsPortBindingIP, ssPort) if err != nil { return "", "", fmt.Errorf("Problem finding SS API port: %s", err) } - fedBaseURL = fmt.Sprintf("https://"+ssapiPortBinding.HostIP+":%s", ssapiPortBinding.HostPort) + fedBaseURL = fmt.Sprintf("https://%s:%s", ssapiPortBinding.HostIP, ssapiPortBinding.HostPort) return } -// findPortBinding finds a matching port binding for the given host/port in the `nat.PortMap`. +// findPortBinding finds a matching port binding for the given host/port in the `network.PortMap`. // // This function will return the first port binding that matches the given host IP. If a // `0.0.0.0` binding is found, we will assume that it is listening on all interfaces, // including the `hsPortBindingIP`, and return a binding with the `hsPortBindingIP` as // the host IP. -func findPortBinding(p nat.PortMap, hsPortBindingIP string, port int) (portBinding nat.PortBinding, err error) { +func findPortBinding(p network.PortMap, hsPortBindingIP string, port int) (network.PortBinding, error) { portString := fmt.Sprintf("%d/tcp", port) - portBindings, ok := p[nat.Port(portString)] + parsedPort, err := network.ParsePort(portString) + if err != nil { + return network.PortBinding{}, fmt.Errorf("port %s failed to be parsed: %v", portString, err) + } + portBindings, ok := p[parsedPort] if !ok { - return nat.PortBinding{}, fmt.Errorf("port %s not exposed - exposed ports: %v", portString, p) + return network.PortBinding{}, fmt.Errorf("port %s not exposed - exposed ports: %v", portString, p) } if len(portBindings) == 0 { - return nat.PortBinding{}, fmt.Errorf("port %s exposed with not mapped port: %+v", portString, p) + return network.PortBinding{}, fmt.Errorf("port %s exposed with not mapped port: %+v", portString, p) } for _, pb := range portBindings { - if pb.HostIP == hsPortBindingIP { + pbHostIP := pb.HostIP.String() + if pbHostIP == hsPortBindingIP { return pb, nil - } else if pb.HostIP == "0.0.0.0" { + } else if pbHostIP == "0.0.0.0" { // `0.0.0.0` means "all interfaces", so we can assume that this will be listening // for connections from `hsPortBindingIP` as well. - return nat.PortBinding{ - HostIP: hsPortBindingIP, - HostPort: pb.HostPort, - }, nil - } else if pb.HostIP == "" && hsPortBindingIP == "127.0.0.1" { + return getPortBinding(hsPortBindingIP, pb.HostPort) + } else if pbHostIP == "" && hsPortBindingIP == "127.0.0.1" { // `HostIP` can be empty in certain environments (observed with podman v4.3.1). We // will assume this is only a binding for `127.0.0.1`. - return nat.PortBinding{ - HostIP: hsPortBindingIP, - HostPort: pb.HostPort, - }, nil + return getPortBinding(hsPortBindingIP, pb.HostPort) } } - return nat.PortBinding{}, fmt.Errorf("unable to find matching port binding for %s %s: %+v", hsPortBindingIP, portString, p) + return network.PortBinding{}, fmt.Errorf("unable to find matching port binding for %s %s: %+v", hsPortBindingIP, portString, p) +} + +func getPortBinding(hsPortBindingIP string, hostPort string) (network.PortBinding, error) { + hostAddr, err := netip.ParseAddr(hsPortBindingIP) + if err != nil { + return network.PortBinding{}, fmt.Errorf("hsPortBindingIP %s failed to be parsed: %v", hsPortBindingIP, err) + } + return network.PortBinding{ + HostIP: hostAddr, + HostPort: hostPort, + }, nil } type result struct { diff --git a/internal/docker/deployer.go b/internal/docker/deployer.go index 6255a945..ad453aab 100644 --- a/internal/docker/deployer.go +++ b/internal/docker/deployer.go @@ -30,14 +30,14 @@ import ( "sync" "time" - "github.com/docker/docker/client" "github.com/matrix-org/complement/internal" complementRuntime "github.com/matrix-org/complement/runtime" + "github.com/moby/moby/client" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/api/types/mount" - "github.com/docker/docker/api/types/network" + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/image" + "github.com/moby/moby/api/types/mount" + "github.com/moby/moby/api/types/network" "github.com/matrix-org/complement/config" ) @@ -140,7 +140,7 @@ func (d *Deployer) Deploy(ctx context.Context, blueprintName string) (*Deploymen HS: make(map[string]*HomeserverDeployment), Config: d.config, } - images, err := d.Docker.ImageList(ctx, image.ListOptions{ + images, err := d.Docker.ImageList(ctx, client.ImageListOptions{ Filters: label( "complement_pkg="+d.config.PackageNamespace, "complement_blueprint="+blueprintName, @@ -149,7 +149,7 @@ func (d *Deployer) Deploy(ctx context.Context, blueprintName string) (*Deploymen if err != nil { return nil, fmt.Errorf("Deploy: failed to ImageList: %w", err) } - if len(images) == 0 { + if len(images.Items) == 0 { return nil, fmt.Errorf("Deploy: No images have been built for blueprint %s", blueprintName) } networkName, err := createNetworkIfNotExists(d.Docker, d.config.PackageNamespace, blueprintName) @@ -160,7 +160,7 @@ func (d *Deployer) Deploy(ctx context.Context, blueprintName string) (*Deploymen // deploy images in parallel var mu sync.Mutex // protects mutable values like the counter and errors var wg sync.WaitGroup - wg.Add(len(images)) // ensure we wait until all images have deployed + wg.Add(len(images.Items)) // ensure we wait until all images have deployed deployImg := func(img image.Summary) error { defer wg.Done() mu.Lock() @@ -197,7 +197,7 @@ func (d *Deployer) Deploy(ctx context.Context, blueprintName string) (*Deploymen } var lastErr error - for _, img := range images { + for _, img := range images.Items { go func(i image.Summary) { err := deployImg(i) if err != nil { @@ -224,7 +224,7 @@ func (d *Deployer) Destroy(dep *Deployment, printServerLogs bool, testName strin // If we want the logs we gracefully stop the containers to allow // the logs to be flushed. oneSecond := 1 - err := d.Docker.ContainerStop(context.Background(), hsDep.ContainerID, container.StopOptions{ + _, err := d.Docker.ContainerStop(context.Background(), hsDep.ContainerID, client.ContainerStopOptions{ Timeout: &oneSecond, }) if err != nil { @@ -247,7 +247,7 @@ func (d *Deployer) Destroy(dep *Deployment, printServerLogs bool, testName strin log.Printf("Post test script result: %s", string(result)) } - err = d.Docker.ContainerRemove(context.Background(), hsDep.ContainerID, container.RemoveOptions{ + _, err = d.Docker.ContainerRemove(context.Background(), hsDep.ContainerID, client.ContainerRemoveOptions{ Force: true, }) if err != nil { @@ -267,7 +267,7 @@ func (d *Deployer) executePostScript(hsDep *HomeserverDeployment, testName strin func (d *Deployer) PauseServer(hsDep *HomeserverDeployment) error { ctx := context.Background() - err := d.Docker.ContainerPause(ctx, hsDep.ContainerID) + _, err := d.Docker.ContainerPause(ctx, hsDep.ContainerID, client.ContainerPauseOptions{}) if err != nil { return fmt.Errorf("failed to pause container %s: %s", hsDep.ContainerID, err) } @@ -276,7 +276,7 @@ func (d *Deployer) PauseServer(hsDep *HomeserverDeployment) error { func (d *Deployer) UnpauseServer(hsDep *HomeserverDeployment) error { ctx := context.Background() - err := d.Docker.ContainerUnpause(ctx, hsDep.ContainerID) + _, err := d.Docker.ContainerUnpause(ctx, hsDep.ContainerID, client.ContainerUnpauseOptions{}) if err != nil { return fmt.Errorf("failed to unpause container %s: %s", hsDep.ContainerID, err) } @@ -286,7 +286,7 @@ func (d *Deployer) UnpauseServer(hsDep *HomeserverDeployment) error { func (d *Deployer) StopServer(hsDep *HomeserverDeployment) error { ctx := context.Background() secs := int(d.config.SpawnHSTimeout.Seconds()) - err := d.Docker.ContainerStop(ctx, hsDep.ContainerID, container.StopOptions{ + _, err := d.Docker.ContainerStop(ctx, hsDep.ContainerID, client.ContainerStopOptions{ Timeout: &secs, }) if err != nil { @@ -308,7 +308,7 @@ func (d *Deployer) Restart(hsDep *HomeserverDeployment) error { func (d *Deployer) StartServer(hsDep *HomeserverDeployment) error { ctx := context.Background() - err := d.Docker.ContainerStart(ctx, hsDep.ContainerID, container.StartOptions{}) + _, err := d.Docker.ContainerStart(ctx, hsDep.ContainerID, client.ContainerStartOptions{}) if err != nil { return fmt.Errorf("failed to start container %s: %s", hsDep.ContainerID, err) } @@ -375,49 +375,55 @@ func deployImage( log.Printf("Sharing %v host environment variables with container", env) } - body, err := docker.ContainerCreate(ctx, &container.Config{ - Image: imageID, - Env: env, - //Cmd: d.ImageArgs, - Labels: map[string]string{ - complementLabel: contextStr, - "complement_blueprint": blueprintName, - "complement_pkg": pkgNamespace, - "complement_hs_name": hsName, + body, err := docker.ContainerCreate(ctx, client.ContainerCreateOptions{ + Config: &container.Config{ + Image: imageID, + Env: env, + //Cmd: d.ImageArgs, + Labels: map[string]string{ + complementLabel: contextStr, + "complement_blueprint": blueprintName, + "complement_pkg": pkgNamespace, + "complement_hs_name": hsName, + }, }, - }, &container.HostConfig{ - CapAdd: []string{"NET_ADMIN"}, // TODO : this should be some sort of option - // We use `PublishAllPorts` because although Complement only requires the ports 8008 - // and 8448 to be accessible in the image, other custom out-of-repo tests may use - // additional ports that are specific to their own application. - // - // Ideally, we would only bind to `cfg.HSPortBindingIP` but there isn't a way to - // specify the `HostIP` when using `PublishAllPorts`. And although, we could specify - // a manual port mapping, it's not compatible with also having `PublishAllPorts` set - // to true (we run into `address already in use` errors). Binding to all interfaces - // means we're also listening on `cfg.HSPortBindingIP` so it's good enough. - PublishAllPorts: true, - ExtraHosts: extraHosts, - Mounts: mounts, - // https://docs.docker.com/engine/containers/resource_constraints/ - Resources: container.Resources{ - // Constrain the the number of CPU cores this container can use - // - // The number of CPU cores in 1e9 increments + HostConfig: &container.HostConfig{ + CapAdd: []string{"NET_ADMIN"}, // TODO : this should be some sort of option + // We use `PublishAllPorts` because although Complement only requires the ports 8008 + // and 8448 to be accessible in the image, other custom out-of-repo tests may use + // additional ports that are specific to their own application. // - // `NanoCPUs` is the option that is "Applicable to all platforms" instead of - // `CPUPeriod`/`CPUQuota` (Unix only) or `CPUCount`/`CPUPercent` (Windows only). - NanoCPUs: int64(cfg.ContainerCPUCores * 1e9), - // Constrain the maximum memory the container can use - Memory: cfg.ContainerMemoryBytes, + // Ideally, we would only bind to `cfg.HSPortBindingIP` but there isn't a way to + // specify the `HostIP` when using `PublishAllPorts`. And although, we could specify + // a manual port mapping, it's not compatible with also having `PublishAllPorts` set + // to true (we run into `address already in use` errors). Binding to all interfaces + // means we're also listening on `cfg.HSPortBindingIP` so it's good enough. + PublishAllPorts: true, + ExtraHosts: extraHosts, + Mounts: mounts, + // https://docs.docker.com/engine/containers/resource_constraints/ + Resources: container.Resources{ + // Constrain the the number of CPU cores this container can use + // + // The number of CPU cores in 1e9 increments + // + // `NanoCPUs` is the option that is "Applicable to all platforms" instead of + // `CPUPeriod`/`CPUQuota` (Unix only) or `CPUCount`/`CPUPercent` (Windows only). + NanoCPUs: int64(cfg.ContainerCPUCores * 1e9), + // Constrain the maximum memory the container can use + Memory: cfg.ContainerMemoryBytes, + }, }, - }, &network.NetworkingConfig{ - EndpointsConfig: map[string]*network.EndpointSettings{ - networkName: { - Aliases: []string{hsName}, + NetworkingConfig: &network.NetworkingConfig{ + EndpointsConfig: map[string]*network.EndpointSettings{ + networkName: { + Aliases: []string{hsName}, + }, }, }, - }, nil, containerName) + Platform: nil, + Name: containerName, + }) if err != nil { return nil, fmt.Errorf("ContainerCreate: %s", err) } @@ -472,7 +478,7 @@ func deployImage( return stubDeployment, fmt.Errorf("failed to copy CA key to container: %s", err) } - err = docker.ContainerStart(ctx, containerID, container.StartOptions{}) + _, err = docker.ContainerStart(ctx, containerID, client.ContainerStartOptions{}) if err != nil { return stubDeployment, fmt.Errorf("ContainerStart: %s", err) } @@ -493,11 +499,11 @@ func deployImage( ) } - inspect, err := docker.ContainerInspect(ctx, containerID) + inspect, err := docker.ContainerInspect(ctx, containerID, client.ContainerInspectOptions{}) if err != nil { return stubDeployment, fmt.Errorf("ContainerInspect: %s", err) } - for vol := range inspect.Config.Volumes { + for vol := range inspect.Container.Config.Volumes { log.Printf( "WARNING: %s has a named VOLUME %s - volumes can lead to unpredictable behaviour due to "+ "test pollution. Remove the VOLUME in the Dockerfile to suppress this message.", containerName, vol, @@ -508,9 +514,9 @@ func deployImage( BaseURL: baseURL, FedBaseURL: fedBaseURL, ContainerID: containerID, - AccessTokens: tokensFromLabels(inspect.Config.Labels), - ApplicationServices: asIDToRegistrationFromLabels(inspect.Config.Labels), - DeviceIDs: deviceIDsFromLabels(inspect.Config.Labels), + AccessTokens: tokensFromLabels(inspect.Container.Config.Labels), + ApplicationServices: asIDToRegistrationFromLabels(inspect.Container.Config.Labels), + DeviceIDs: deviceIDsFromLabels(inspect.Container.Config.Labels), Network: networkName, } @@ -543,7 +549,9 @@ func copyToContainer(docker *client.Client, containerID, path string, data []byt tw.Close() // Put our new fake file in the container volume - err = docker.CopyToContainer(context.Background(), containerID, "/", &buf, container.CopyToContainerOptions{ + _, err = docker.CopyToContainer(context.Background(), containerID, client.CopyToContainerOptions{ + DestinationPath: "/", + Content: &buf, AllowOverwriteDirWithFile: false, }) if err != nil { @@ -567,12 +575,12 @@ func assertHostnameEqual(inputUrl string, expectedHostname string) error { // getHostAccessibleHomeserverURLs returns URLs that are accessible from the host // machine (outside the container) for the homeserver's client API and federation API. func getHostAccessibleHomeserverURLs(ctx context.Context, docker *client.Client, containerID string, hsPortBindingIP string) (baseURL string, fedBaseURL string, err error) { - inspectResponse, err := inspectContainer(ctx, docker, containerID) + inspectResult, err := inspectContainer(ctx, docker, containerID) if err != nil { return "", "", fmt.Errorf("failed to inspect ports: %w", err) } - baseURL, fedBaseURL, err = endpoints(inspectResponse.NetworkSettings.Ports, hsPortBindingIP, 8008, 8448) + baseURL, fedBaseURL, err = endpoints(inspectResult.Container.NetworkSettings.Ports, hsPortBindingIP, 8008, 8448) // Sanity check that the URLs match the expected configured binding IP. It's // also important that we use the canonical publicly accessible hostname for the @@ -595,15 +603,15 @@ func waitForPorts(ctx context.Context, docker *client.Client, containerID string // We need to hammer the inspect endpoint until the ports show up, they don't appear immediately. inspectStartTime := time.Now() for time.Since(inspectStartTime) < time.Second { - inspectResponse, err := inspectContainer(ctx, docker, containerID) + inspectResult, err := inspectContainer(ctx, docker, containerID) if inspectionErr, ok := err.(*containerInspectionError); ok && inspectionErr.Fatal { // If the error is fatal, we should not retry. return fmt.Errorf("Fatal inspection error: %s", err) } // Check to see if we can see the ports yet - _, csPortErr := findPortBinding(inspectResponse.NetworkSettings.Ports, hsPortBindingIP, 8008) - _, ssPortErr := findPortBinding(inspectResponse.NetworkSettings.Ports, hsPortBindingIP, 8448) + _, csPortErr := findPortBinding(inspectResult.Container.NetworkSettings.Ports, hsPortBindingIP, 8008) + _, ssPortErr := findPortBinding(inspectResult.Container.NetworkSettings.Ports, hsPortBindingIP, 8448) if csPortErr == nil && ssPortErr == nil { break } @@ -630,23 +638,23 @@ func inspectContainer( ctx context.Context, docker *client.Client, containerID string, -) (inspectResponse container.InspectResponse, err error) { - inspectResponse, err = docker.ContainerInspect(ctx, containerID) +) (inspectResult client.ContainerInspectResult, err error) { + inspectResult, err = docker.ContainerInspect(ctx, containerID, client.ContainerInspectOptions{}) if err != nil { - return container.InspectResponse{}, &containerInspectionError{ + return client.ContainerInspectResult{}, &containerInspectionError{ msg: err.Error(), Fatal: false, } } - if inspectResponse.State != nil && !inspectResponse.State.Running { + if inspectResult.Container.State != nil && !inspectResult.Container.State.Running { // the container exited, bail out with a container ID for logs - return container.InspectResponse{}, &containerInspectionError{ - msg: fmt.Sprintf("container (%s) is not running, state=%v", containerID, inspectResponse.State.Status), + return client.ContainerInspectResult{}, &containerInspectionError{ + msg: fmt.Sprintf("container (%s) is not running, state=%v", containerID, inspectResult.Container.State.Status), Fatal: true, } } - return inspectResponse, nil + return inspectResult, nil } // waitForContainer waits until a homeserver deployment is ready to serve requests. @@ -660,15 +668,15 @@ func waitForContainer(ctx context.Context, docker *client.Client, hsDep *Homeser lastErr = fmt.Errorf("timed out checking for homeserver to be up: %s", lastErr) return } - inspect, err := docker.ContainerInspect(ctx, hsDep.ContainerID) + inspect, err := docker.ContainerInspect(ctx, hsDep.ContainerID, client.ContainerInspectOptions{}) if err != nil { lastErr = fmt.Errorf("inspect container %s => error: %s", hsDep.ContainerID, err) time.Sleep(50 * time.Millisecond) continue } - if inspect.State.Health != nil && - inspect.State.Health.Status != "healthy" { - lastErr = fmt.Errorf("inspect container %s => health: %s", hsDep.ContainerID, inspect.State.Health.Status) + if inspect.Container.State.Health != nil && + inspect.Container.State.Health.Status != "healthy" { + lastErr = fmt.Errorf("inspect container %s => health: %s", hsDep.ContainerID, inspect.Container.State.Health.Status) time.Sleep(50 * time.Millisecond) continue } diff --git a/internal/docker/labels.go b/internal/docker/labels.go index 98f5caf9..69ed96fc 100644 --- a/internal/docker/labels.go +++ b/internal/docker/labels.go @@ -3,15 +3,15 @@ package docker import ( "strings" - "github.com/docker/docker/api/types/filters" + "github.com/moby/moby/client" "github.com/matrix-org/complement/b" ) // label returns a filter for the presence of certain labels ("complement_context") or a match of // labels ("complement_blueprint=foo"). -func label(labelFilters ...string) filters.Args { - f := filters.NewArgs() +func label(labelFilters ...string) client.Filters { + f := client.Filters{} // label= or label== for _, in := range labelFilters { f.Add("label", in) diff --git a/runtime/hs.go b/runtime/hs.go index 2037953f..740f5027 100644 --- a/runtime/hs.go +++ b/runtime/hs.go @@ -3,8 +3,8 @@ package runtime import ( "context" - "github.com/docker/docker/client" "github.com/matrix-org/complement/ct" + "github.com/moby/moby/client" ) const ( @@ -18,8 +18,11 @@ var Homeserver string // ContainerKillFunc is used to destroy a container, it can be overwritten by Homeserver implementations // to e.g. gracefully stop a container. -var ContainerKillFunc = func(client *client.Client, containerID string) error { - return client.ContainerKill(context.Background(), containerID, "KILL") +var ContainerKillFunc = func(cli *client.Client, containerID string) error { + _, err := cli.ContainerKill(context.Background(), containerID, client.ContainerKillOptions{ + Signal: "SIGKILL", + }) + return err } // Skip the test (via t.Skipf) if the homeserver being tested matches one of the homeservers, else return. diff --git a/runtime/hs_dendrite.go b/runtime/hs_dendrite.go index 54ad9928..9f443ce0 100644 --- a/runtime/hs_dendrite.go +++ b/runtime/hs_dendrite.go @@ -6,8 +6,7 @@ package runtime import ( "context" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/client" + "github.com/moby/moby/client" ) func init() { @@ -16,7 +15,7 @@ func init() { // extract e.g. coverage reports. ContainerKillFunc = func(client *client.Client, containerID string) error { oneSecond := 1 - return client.ContainerStop(context.Background(), containerID, container.StopOptions{ + return client.ContainerStop(context.Background(), containerID, client.ContainerStopOptions{ Timeout: &oneSecond, }) } From 00acbf1c91d656376c5afa5684d86b031fc27113 Mon Sep 17 00:00:00 2001 From: Andrew Ferrazzutti Date: Tue, 4 Aug 2026 10:17:06 -0400 Subject: [PATCH 2/3] Migrate from ContainerStatsOneShot --- cmd/perftest/snapshot.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/perftest/snapshot.go b/cmd/perftest/snapshot.go index ef9b2892..9b407822 100644 --- a/cmd/perftest/snapshot.go +++ b/cmd/perftest/snapshot.go @@ -7,6 +7,7 @@ import ( "github.com/matrix-org/complement/internal/docker" "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" ) type Snapshot struct { @@ -26,7 +27,7 @@ type Snapshot struct { func snapshotStats(spanName, desc string, deployment *docker.Deployment, absDuration, duration time.Duration) (snapshots []Snapshot) { for hsName, hsInfo := range deployment.HS { - stats, err := deployment.Deployer.Docker.ContainerStatsOneShot(context.Background(), hsInfo.ContainerID) + stats, err := deployment.Deployer.Docker.ContainerStats(context.Background(), hsInfo.ContainerID, client.ContainerStatsOptions{}) if err != nil { return nil } From 33290a0f686977d5c3815728fe305a152e65496a Mon Sep 17 00:00:00 2001 From: Andrew Ferrazzutti Date: Tue, 4 Aug 2026 13:34:03 -0400 Subject: [PATCH 3/3] Fix runtime/hs_dendrite.go --- runtime/hs_dendrite.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/runtime/hs_dendrite.go b/runtime/hs_dendrite.go index 9f443ce0..a80899e7 100644 --- a/runtime/hs_dendrite.go +++ b/runtime/hs_dendrite.go @@ -13,10 +13,11 @@ func init() { Homeserver = Dendrite // For Dendrite, we want to always stop the container gracefully, as this is needed to // extract e.g. coverage reports. - ContainerKillFunc = func(client *client.Client, containerID string) error { + ContainerKillFunc = func(cli *client.Client, containerID string) error { oneSecond := 1 - return client.ContainerStop(context.Background(), containerID, client.ContainerStopOptions{ + _, err := cli.ContainerStop(context.Background(), containerID, client.ContainerStopOptions{ Timeout: &oneSecond, }) + return err } }