diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 5f998a4..e9d93e6 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -77,7 +77,7 @@ jobs: make test - name: Create k8s Kind Cluster - uses: helm/kind-action@v1.9.0 + uses: helm/kind-action@v1.10.0 with: install_only: true diff --git a/go.mod b/go.mod index 33a5376..a66273c 100644 --- a/go.mod +++ b/go.mod @@ -6,12 +6,12 @@ require ( cloud.google.com/go/storage v1.42.0 github.com/Masterminds/semver/v3 v3.2.1 github.com/avast/retry-go/v4 v4.6.0 - github.com/aws/aws-sdk-go v1.53.21 + github.com/aws/aws-sdk-go v1.54.7 github.com/docker/docker v26.1.4+incompatible github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/lib/pq v1.10.9 github.com/meilisearch/meilisearch-go v0.26.3 - github.com/metal-stack/metal-lib v0.16.3 + github.com/metal-stack/metal-lib v0.17.0 github.com/metal-stack/v v1.0.3 github.com/mholt/archiver/v3 v3.5.1 github.com/olekukonko/tablewriter v0.0.5 @@ -19,13 +19,13 @@ require ( github.com/redis/go-redis/v9 v9.5.3 github.com/robfig/cron/v3 v3.0.1 github.com/spf13/afero v1.11.0 - github.com/spf13/cobra v1.8.0 + github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.31.0 go.etcd.io/etcd/client/v3 v3.5.14 golang.org/x/sync v0.7.0 - google.golang.org/api v0.183.0 + google.golang.org/api v0.185.0 google.golang.org/grpc v1.64.0 google.golang.org/protobuf v1.34.2 gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.2 @@ -37,8 +37,8 @@ require ( ) require ( - cloud.google.com/go v0.114.0 // indirect - cloud.google.com/go/auth v0.5.1 // indirect + cloud.google.com/go v0.115.0 // indirect + cloud.google.com/go/auth v0.5.2 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect cloud.google.com/go/compute/metadata v0.3.0 // indirect cloud.google.com/go/iam v1.1.8 // indirect @@ -82,8 +82,8 @@ require ( github.com/google/s2a-go v0.1.7 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.4 // indirect - github.com/gorilla/websocket v1.5.2 // indirect + github.com/googleapis/gax-go/v2 v2.12.5 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/imdario/mergo v0.3.16 // indirect @@ -135,7 +135,7 @@ require ( github.com/tklauser/numcpus v0.8.0 // indirect github.com/ulikunitz/xz v0.5.12 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.54.0 // indirect + github.com/valyala/fasthttp v1.55.0 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect go.etcd.io/etcd/api/v3 v3.5.14 // indirect @@ -149,16 +149,16 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.24.0 // indirect - golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 // indirect + golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sys v0.21.0 // indirect golang.org/x/term v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect - google.golang.org/genproto v0.0.0-20240610135401-a8a62080eff3 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 // indirect + google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240624140628-dc46fd24d27d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d // indirect gopkg.in/cenkalti/backoff.v2 v2.2.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index 7aacbcc..924ba1f 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.114.0 h1:OIPFAdfrFDFO2ve2U7r/H5SwSbBzEdrBdE7xkgwc+kY= -cloud.google.com/go v0.114.0/go.mod h1:ZV9La5YYxctro1HTPug5lXH/GefROyW8PPD4T8n9J8E= -cloud.google.com/go/auth v0.5.1 h1:0QNO7VThG54LUzKiQxv8C6x1YX7lUrzlAa1nVLF8CIw= -cloud.google.com/go/auth v0.5.1/go.mod h1:vbZT8GjzDf3AVqCcQmqeeM32U9HBFc32vVVAbwDsa6s= +cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= +cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= +cloud.google.com/go/auth v0.5.2 h1:xzzYbfrv7xI5oPzzu11RT66GnNhRrWcVG9TXEVxx86Y= +cloud.google.com/go/auth v0.5.2/go.mod h1:b4acV+jLQDyjwm4OXHYjNvRi4jvGBzHWJRtJcy+2P4g= cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= @@ -34,8 +34,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA= github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE= -github.com/aws/aws-sdk-go v1.53.21 h1:vAXk3mJQqveg1H3uZaUBaGXrKWa97hc9zBhudsDZugA= -github.com/aws/aws-sdk-go v1.53.21/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aws/aws-sdk-go v1.54.7 h1:k1wJ+NMOsXgq/Lsa0y1mS0DFoDeHFPcz2OjCq5H5Mjg= +github.com/aws/aws-sdk-go v1.54.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -66,7 +66,7 @@ github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8 github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= @@ -178,11 +178,11 @@ 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/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= -github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg= -github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI= +github.com/googleapis/gax-go/v2 v2.12.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA= +github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.2 h1:qoW6V1GT3aZxybsbC6oLnailWnB+qTMVwMreOso9XUw= -github.com/gorilla/websocket v1.5.2/go.mod h1:0n9H61RBAcf5/38py2MCYbxzPIY9rOkpvvMT24Rqs30= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= @@ -238,8 +238,8 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/meilisearch/meilisearch-go v0.26.3 h1:EYt+C1n7IvjKzgXM3xqce5iJzNBq33F7ayZOKx96TKY= github.com/meilisearch/meilisearch-go v0.26.3/go.mod h1:SxuSqDcPBIykjWz1PX+KzsYzArNLSCadQodWs8extS0= -github.com/metal-stack/metal-lib v0.16.3 h1:xJr6P9GauQK49aoFH0bFyye5kRGmt87PomokulUm4Go= -github.com/metal-stack/metal-lib v0.16.3/go.mod h1:nyNGI4DZFOcWbSoq2Y6V3SHpFxuXBIqYBZHTb6cy//s= +github.com/metal-stack/metal-lib v0.17.0 h1:0fCRUtYweJ5wbUwiEalFGiHkEz0mZwTWQUIIo3Npzkw= +github.com/metal-stack/metal-lib v0.17.0/go.mod h1:nyNGI4DZFOcWbSoq2Y6V3SHpFxuXBIqYBZHTb6cy//s= github.com/metal-stack/v v1.0.3 h1:Sh2oBlnxrCUD+mVpzfC8HiqL045YWkxs0gpTvkjppqs= github.com/metal-stack/v v1.0.3/go.mod h1:YTahEu7/ishwpYKnp/VaW/7nf8+PInogkfGwLcGPdXg= github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= @@ -343,8 +343,8 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= @@ -383,8 +383,8 @@ github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0o github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.37.1-0.20220607072126-8a320890c08d/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= -github.com/valyala/fasthttp v1.54.0 h1:cCL+ZZR3z3HPLMVfEYVUMtJqVaui0+gu7Lx63unHwS0= -github.com/valyala/fasthttp v1.54.0/go.mod h1:6dt4/8olwq9QARP/TDuPmWyWcl4byhpvTJ4AAtcz+QM= +github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8= +github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= @@ -436,8 +436,8 @@ golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 h1:LoYXNGAShUG3m/ehNk4iFctuhGX/+R1ZpfJ4/ia80JM= -golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -518,20 +518,20 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -google.golang.org/api v0.183.0 h1:PNMeRDwo1pJdgNcFQ9GstuLe/noWKIc89pRWRLMvLwE= -google.golang.org/api v0.183.0/go.mod h1:q43adC5/pHoSZTx5h2mSmdF7NcyfW9JuDyIOJAgS9ZQ= +google.golang.org/api v0.185.0 h1:ENEKk1k4jW8SmmaT6RE+ZasxmxezCrD5Vw4npvr+pAU= +google.golang.org/api v0.185.0/go.mod h1:HNfvIkJGlgrIlrbYkAm9W9IdkmKZjOTVh33YltygGbg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240610135401-a8a62080eff3 h1:8RTI1cmuvdY9J7q/jpJWEj5UfgWjhV5MCoXaYmwLBYQ= -google.golang.org/genproto v0.0.0-20240610135401-a8a62080eff3/go.mod h1:qb66gsewNb7Ghv1enkhJiRfYGWUklv3n6G8UvprOhzA= -google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3 h1:QW9+G6Fir4VcRXVH8x3LilNAb6cxBGLa6+GM4hRwexE= -google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3/go.mod h1:kdrSS/OiLkPrNUpzD4aHgCq2rVuC/YRxok32HXZ4vRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 h1:9Xyg6I9IWQZhRVfCWjKK+l6kI0jHcPesVlMnT//aHNo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d h1:PksQg4dV6Sem3/HkBX+Ltq8T0ke0PKIRBNBatoDTVls= +google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:s7iA721uChleev562UJO2OYB0PPT9CMFjV+Ce7VJH5M= +google.golang.org/genproto/googleapis/api v0.0.0-20240624140628-dc46fd24d27d h1:Aqf0fiIdUQEj0Gn9mKFFXoQfTTEaNopWpfVyYADxiSg= +google.golang.org/genproto/googleapis/api v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:Od4k8V1LQSizPRUK4OzZ7TBE/20k+jPczUDAEyvn69Y= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d h1:k3zyW3BYYR30e8v3x0bTDdE9vpYFjZHK+HcyqkrppWk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= diff --git a/integration/etcd_test.go b/integration/etcd_test.go index 5bb9cf6..85d1ca3 100644 --- a/integration/etcd_test.go +++ b/integration/etcd_test.go @@ -4,6 +4,8 @@ package integration_test import ( "context" + "fmt" + "strconv" "testing" "time" @@ -25,6 +27,16 @@ func Test_ETCD_Restore(t *testing.T) { }) } +func Test_ETCD_RestoreLatestFromMultipleBackups(t *testing.T) { + restoreLatestFromMultipleBackupsFlow(t, &flowSpec{ + databaseType: examples.Etcd, + sts: examples.EtcdSts, + backingResources: examples.EtcdBackingResources, + addTestDataWithIndex: addEtcdTestDataWithIndex, + verifyTestDataWithIndex: verifyEtcdTestDataWithIndex, + }) +} + func newEtcdClient(t *testing.T, ctx context.Context) *clientv3.Client { var cli *clientv3.Client @@ -65,3 +77,23 @@ func verifyEtcdTestData(t *testing.T, ctx context.Context) { assert.Equal(t, "1", string(ev.Key)) assert.Equal(t, "I am precious", string(ev.Value)) } +func addEtcdTestDataWithIndex(t *testing.T, ctx context.Context, index int) { + cli := newEtcdClient(t, ctx) + defer cli.Close() + + _, err := cli.Put(ctx, strconv.Itoa(index), fmt.Sprintf("idx-%d", index)) + require.NoError(t, err) +} + +func verifyEtcdTestDataWithIndex(t *testing.T, ctx context.Context, index int) { + cli := newEtcdClient(t, ctx) + defer cli.Close() + + resp, err := cli.Get(ctx, strconv.Itoa(index)) + require.NoError(t, err) + require.Len(t, resp.Kvs, 1) + + ev := resp.Kvs[0] + assert.Equal(t, strconv.Itoa(index), string(ev.Key)) + assert.Equal(t, fmt.Sprintf("idx-%d", index), string(ev.Value)) +} diff --git a/integration/keydb_test.go b/integration/keydb_test.go index 621ee1b..c3fabfa 100644 --- a/integration/keydb_test.go +++ b/integration/keydb_test.go @@ -17,3 +17,13 @@ func Test_KeyDB_Restore(t *testing.T) { verifyTestData: verifyRedisTestData, }) } + +func Test_KeyDB_RestoreLatestFromMultipleBackups(t *testing.T) { + restoreLatestFromMultipleBackupsFlow(t, &flowSpec{ + databaseType: examples.Redis, + sts: examples.RedisSts, + backingResources: examples.RedisBackingResources, + addTestDataWithIndex: addRedisTestDataWithIndex, + verifyTestDataWithIndex: verifyRedisTestDataWithIndex, + }) +} diff --git a/integration/main_test.go b/integration/main_test.go index 9d3485b..c29fec9 100644 --- a/integration/main_test.go +++ b/integration/main_test.go @@ -33,10 +33,12 @@ import ( type flowSpec struct { databaseType string - sts func(namespace string) *appsv1.StatefulSet - backingResources func(namespace string) []client.Object - addTestData func(t *testing.T, ctx context.Context) - verifyTestData func(t *testing.T, ctx context.Context) + sts func(namespace string) *appsv1.StatefulSet + backingResources func(namespace string) []client.Object + addTestData func(t *testing.T, ctx context.Context) + addTestDataWithIndex func(t *testing.T, ctx context.Context, index int) + verifyTestData func(t *testing.T, ctx context.Context) + verifyTestDataWithIndex func(t *testing.T, ctx context.Context, index int) } type upgradeFlowSpec struct { @@ -175,6 +177,123 @@ func restoreFlow(t *testing.T, spec *flowSpec) { spec.verifyTestData(t, ctx) } +func restoreLatestFromMultipleBackupsFlow(t *testing.T, spec *flowSpec) { + t.Log("running restore with empty datadir flow") + var ( + ctx, cancel = context.WithTimeout(context.Background(), 10*time.Minute) + ns = testNamespace(t) + ) + + defer cancel() + + cleanup := func() { + t.Log("running cleanup") + + err := c.Delete(ctx, ns) + require.NoError(t, client.IgnoreNotFound(err), "cleanup did not succeed") + + err = waitUntilNotFound(ctx, &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: ns.Name, + }, + }) + require.NoError(t, err, "cleanup did not succeed") + } + cleanup() + defer cleanup() + + err := c.Create(ctx, ns) + require.NoError(t, client.IgnoreAlreadyExists(err)) + + t.Log("applying resource manifests") + + objects := func() []client.Object { + objects := []client.Object{spec.sts(ns.Name)} + objects = append(objects, spec.backingResources(ns.Name)...) + return objects + } + + for _, o := range objects() { + o := o + err = c.Create(ctx, o) + require.NoError(t, err) + } + + podName := spec.sts(ns.Name).Name + "-0" + + err = waitForPodRunning(ctx, podName, ns.Name) + require.NoError(t, err) + + t.Log("adding multiple test data to database") + + brsc, err := brsclient.New(ctx, "http://localhost:8000") + require.NoError(t, err) + + lastindex := 0 + for i := range 10 { + t.Log("adding test data", "index", i) + spec.addTestDataWithIndex(t, ctx, i) + + t.Log("taking a backup") + _, err = brsc.DatabaseServiceClient().CreateBackup(ctx, &v1.CreateBackupRequest{}) + if err != nil && !errors.Is(err, constants.ErrBackupAlreadyInProgress) { + require.NoError(t, err) + } + lastindex = i + } + + var backup *v1.Backup + err = retry.Do(func() error { + backups, err := brsc.BackupServiceClient().ListBackups(ctx, &v1.ListBackupsRequest{}) + if err != nil { + return err + } + + if len(backups.GetBackups()) == 0 { + return fmt.Errorf("no backups were made yet") + } + + backup = backups.GetBackups()[0] + + return nil + }, retry.Context(ctx), retry.Attempts(0), retry.MaxDelay(2*time.Second)) + require.NoError(t, err) + require.NotNil(t, backup) + + t.Log("remove sts and delete data volume") + + err = c.Delete(ctx, spec.sts(ns.Name)) + require.NoError(t, err) + + err = c.Delete(ctx, &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "data-" + podName, + Namespace: ns.Name, + }, + }) + require.NoError(t, err) + + err = waitUntilNotFound(ctx, &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: ns.Name, + }, + }) + require.NoError(t, err) + + t.Log("recreate sts") + + err = c.Create(ctx, spec.sts(ns.Name)) + require.NoError(t, err) + + err = waitForPodRunning(ctx, podName, ns.Name) + require.NoError(t, err) + + t.Log("verify that data gets restored") + + spec.verifyTestDataWithIndex(t, ctx, lastindex) +} + func upgradeFlow(t *testing.T, spec *upgradeFlowSpec) { t.Log("running upgrade flow") diff --git a/integration/meilisearch_test.go b/integration/meilisearch_test.go index c8b6578..c43d6c4 100644 --- a/integration/meilisearch_test.go +++ b/integration/meilisearch_test.go @@ -5,6 +5,7 @@ package integration_test import ( "context" "fmt" + "strconv" "testing" "github.com/avast/retry-go/v4" @@ -28,6 +29,16 @@ func Test_Meilisearch_Restore(t *testing.T) { }) } +func Test_Meilisearch_RestoreLatestFromMultipleBackups(t *testing.T) { + restoreLatestFromMultipleBackupsFlow(t, &flowSpec{ + databaseType: examples.Meilisearch, + sts: examples.MeilisearchSts, + backingResources: examples.MeilisearchBackingResources, + addTestDataWithIndex: addMeilisearchTestDataWithIndex, + verifyTestDataWithIndex: verifyMeilisearchTestDataWithIndex, + }) +} + func Test_Meilisearch_Upgrade(t *testing.T) { upgradeFlow(t, &upgradeFlowSpec{ flowSpec: flowSpec{ @@ -95,3 +106,34 @@ func verifyMeilisearchTestData(t *testing.T, ctx context.Context) { require.NoError(t, err) assert.Equal(t, "I am precious", testdata["key"]) } + +func addMeilisearchTestDataWithIndex(t *testing.T, ctx context.Context, i int) { + client := newMeilisearchSession(t, ctx) + creationTask, err := client.CreateIndex(&meilisearch.IndexConfig{ + Uid: meilisearchIndex, + PrimaryKey: "id", + }) + require.NoError(t, err) + _, err = client.WaitForTask(creationTask.TaskUID) + require.NoError(t, err) + + index := client.Index(meilisearchIndex) + testdata := map[string]any{ + "id": strconv.Itoa(i), + "key": fmt.Sprintf("idx-%d", i), + } + indexTask, err := index.AddDocuments(testdata, "id") + require.NoError(t, err) + _, err = client.WaitForTask(indexTask.TaskUID) + require.NoError(t, err) +} + +func verifyMeilisearchTestDataWithIndex(t *testing.T, ctx context.Context, i int) { + client := newMeilisearchSession(t, ctx) + index, err := client.GetIndex(meilisearchIndex) + require.NoError(t, err) + testdata := make(map[string]any) + err = index.GetDocument(strconv.Itoa(i), &meilisearch.DocumentQuery{}, &testdata) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("idx-%d", i), testdata["key"]) +} diff --git a/integration/postgres_test.go b/integration/postgres_test.go index bbdc406..4d78530 100644 --- a/integration/postgres_test.go +++ b/integration/postgres_test.go @@ -27,6 +27,16 @@ func Test_Postgres_Restore(t *testing.T) { }) } +func Test_Postgres_RestoreLatestFromMultipleBackups(t *testing.T) { + restoreLatestFromMultipleBackupsFlow(t, &flowSpec{ + databaseType: examples.Postgres, + sts: examples.PostgresSts, + backingResources: examples.PostgresBackingResources, + addTestDataWithIndex: addPostgresTestDataWithIndex, + verifyTestDataWithIndex: verifyPostgresTestDataWithIndex, + }) +} + func Test_Postgres_Upgrade(t *testing.T) { upgradeFlow(t, &upgradeFlowSpec{ flowSpec: flowSpec{ @@ -86,6 +96,42 @@ func addPostgresTestData(t *testing.T, ctx context.Context) { require.NoError(t, err) } +func addPostgresTestDataWithIndex(t *testing.T, ctx context.Context, index int) { + db := newPostgresSession(t, ctx) + defer db.Close() + + var ( + createStmt = `CREATE TABLE IF NOT EXISTS backuprestore ( + data text NOT NULL + );` + insertStmt = fmt.Sprintf("INSERT INTO backuprestore (data) VALUES ('idx-%d');", index) + ) + + _, err := db.Exec(createStmt) + require.NoError(t, err) + + _, err = db.Exec(insertStmt) + require.NoError(t, err) +} + +func verifyPostgresTestDataWithIndex(t *testing.T, ctx context.Context, index int) { + db := newPostgresSession(t, ctx) + defer db.Close() + + rows, err := db.Query(fmt.Sprintf("SELECT \"data\" FROM backuprestore WHERE data='idx-%d';", index)) + require.NoError(t, err) + require.NoError(t, rows.Err()) + defer rows.Close() + + require.True(t, rows.Next()) + var data string + + err = rows.Scan(&data) + require.NoError(t, err) + + assert.Equal(t, fmt.Sprintf("idx-%d", index), data) + assert.False(t, rows.Next()) +} func verifyPostgresTestData(t *testing.T, ctx context.Context) { db := newPostgresSession(t, ctx) defer db.Close() diff --git a/integration/redis_test.go b/integration/redis_test.go index fbd75ad..0a87546 100644 --- a/integration/redis_test.go +++ b/integration/redis_test.go @@ -4,6 +4,8 @@ package integration_test import ( "context" + "fmt" + "strconv" "testing" "time" @@ -25,6 +27,16 @@ func Test_Redis_Restore(t *testing.T) { }) } +func Test_Redis_RestoreLatestFromMultipleBackups(t *testing.T) { + restoreLatestFromMultipleBackupsFlow(t, &flowSpec{ + databaseType: examples.Redis, + sts: examples.RedisSts, + backingResources: examples.RedisBackingResources, + addTestDataWithIndex: addRedisTestDataWithIndex, + verifyTestDataWithIndex: verifyRedisTestDataWithIndex, + }) +} + func newRedisClient(t *testing.T, ctx context.Context) *redis.Client { var cli *redis.Client @@ -61,3 +73,21 @@ func verifyRedisTestData(t *testing.T, ctx context.Context) { require.NotEmpty(t, resp) assert.Equal(t, "I am precious", resp) } + +func addRedisTestDataWithIndex(t *testing.T, ctx context.Context, index int) { + cli := newRedisClient(t, ctx) + defer cli.Close() + + _, err := cli.Set(ctx, strconv.Itoa(index), fmt.Sprintf("idx-%d", index), 1*time.Hour).Result() + require.NoError(t, err) +} + +func verifyRedisTestDataWithIndex(t *testing.T, ctx context.Context, index int) { + cli := newRedisClient(t, ctx) + defer cli.Close() + + resp, err := cli.Get(ctx, strconv.Itoa(index)).Result() + require.NoError(t, err) + require.NotEmpty(t, resp) + assert.Equal(t, fmt.Sprintf("idx-%d", index), resp) +} diff --git a/integration/rethinkdb_test.go b/integration/rethinkdb_test.go index c330ff9..3bf0f51 100644 --- a/integration/rethinkdb_test.go +++ b/integration/rethinkdb_test.go @@ -5,6 +5,7 @@ package integration_test import ( "context" "fmt" + "strconv" "testing" "github.com/metal-stack/backup-restore-sidecar/pkg/generate/examples/examples" @@ -35,6 +36,16 @@ func Test_RethinkDB_Restore(t *testing.T) { }) } +func Test_RethinkDB_RestoreLatestFromMultipleBackups(t *testing.T) { + restoreLatestFromMultipleBackupsFlow(t, &flowSpec{ + databaseType: examples.RethinkDB, + sts: examples.RethinkDbSts, + backingResources: examples.RethinkDbBackingResources, + addTestDataWithIndex: addRethinkDbTestDataWithIndex, + verifyTestDataWithIndex: verifyRethinkDbTestDataWithIndex, + }) +} + func newRethinkdbSession(t *testing.T, ctx context.Context) *r.Session { var session *r.Session err := retry.Do(func() error { @@ -103,3 +114,55 @@ func verifyRethinkDbTestData(t *testing.T, ctx context.Context) { assert.Equal(t, "i am precious", d2.Data) } + +func addRethinkDbTestDataWithIndex(t *testing.T, ctx context.Context, index int) { + session := newRethinkdbSession(t, ctx) + + _, err := r.Expr([]string{rethinkDbDatabaseName}).Difference(r.DBList()).ForEach(func(x r.Term) r.Term { + return r.DBCreate(rethinkDbDatabaseName) + }).RunWrite(session) + require.NoError(t, err) + + db := r.DB(rethinkDbDatabaseName) + + _, err = r.Expr([]string{rethinkDbTable}).Difference(db.TableList()).ForEach(func(r r.Term) r.Term { + return db.TableCreate(r) + }).RunWrite(session) + require.NoError(t, err) + + _, err = r.DB(rethinkDbDatabaseName).Table(rethinkDbTable).Insert(rethinkDbTestData{ + ID: strconv.Itoa(index), + Data: fmt.Sprintf("idx-%d", index), + }).RunWrite(session) + require.NoError(t, err) + + cursor, err := r.DB(rethinkDbDatabaseName).Table(rethinkDbTable).Get(strconv.Itoa(index)).Run(session) + require.NoError(t, err) + + var d1 rethinkDbTestData + err = cursor.One(&d1) + require.NoError(t, err) + require.Equal(t, fmt.Sprintf("idx-%d", index), d1.Data) +} + +func verifyRethinkDbTestDataWithIndex(t *testing.T, ctx context.Context, index int) { + session := newRethinkdbSession(t, ctx) + + var d2 rethinkDbTestData + err := retry.Do(func() error { + cursor, err := r.DB(rethinkDbDatabaseName).Table(rethinkDbTable).Get(strconv.Itoa(index)).Run(session) + if err != nil { + return err + } + + err = cursor.One(&d2) + if err != nil { + return err + } + + return nil + }) + require.NoError(t, err) + + assert.Equal(t, fmt.Sprintf("idx-%d", index), d2.Data) +} diff --git a/proto/Makefile b/proto/Makefile index 2a25041..a8ae72a 100644 --- a/proto/Makefile +++ b/proto/Makefile @@ -1,5 +1,5 @@ MAKEFLAGS += --no-print-directory -BUF_VERSION := 1.32.2 +BUF_VERSION := 1.34.0 _buf: docker run --rm \